// Compute pattern angle of a vector on the sky double procedure AngleFromVector { {double,double} vector = {1.0,1.0}; // Vector }{ double degpi = 180.0 / 3.14159265; double fullcircle = 360.0; double angle = atan2(vector{0},vector{1}) * degpi; // translate into range between 0 and 360 degrees angle = (angle + fullcircle) % fullcircle; return angle; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the OTF observing mode procedure OTFmap_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int nlines_tot = 1; // Total number of lines to scan int n_linesperscan = 1; // Number of lines between two OFFs int n_intoff = 3; // Number of data dumps for the OFF integration time int n_pp = 10; // Number of data dumps per line int n_loadinterval = 1; // number of nods before a load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,2,2,40,10,20,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int toffslew = telescopetimes[6]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Count OFFs by hand, their counter is not returned in the state array int ioff = 0; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 4) { // OFF Integration HIFIConfigureContIntegration(data_time,n_intoff,band,lo_freq,backendreadoutparms); HIFIContOffIntegration(data_time,n_intoff,rates); // OFF counter ioff = ioff + 1; // Check for normal slew after OFF if(state[2] * state[3] < nlines_tot) { HIFIActiveHK("normal",toffslew); } } if(state[0] == 8) { // OTF integration // Check whether we come from the OFF if((state[2] + n_linesperscan - 1) % n_linesperscan == 0) { HIFIConfigureContIntegration(data_time,n_pp,band,lo_freq,backendreadoutparms); } HIFIContOnIntegration(data_time,n_pp,rates); // Check for normal slew towards the OFF if(state[2] % n_linesperscan == 0) { if(ioff % n_loadinterval > 0) { HIFIActiveHK("normal",toffslew); } } } if(state[0] == 9) { // Load slew delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 5) { // Final hold - close observation delay(readoutdead); HIFICloseObs(); } } } ////////////////////////////////////////////////////////////////// // Procedure to compute detailed pre timing for the version of the // frequency switch mode with baseline measurement // {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} procedure FSwitch_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_chop_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_chop_off = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq + min(freq_throw,0.0),lo_freq + max(freq_throw,0.0)); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); CheckDataTaking(backendreadoutparms,data_time_off); CheckFswOutOfBand(band,lo_freq,freq_throw,backendreadoutparms); int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int on_inttime = 2 * n_chop_on * data_time; int off_inttime = 2 * n_chop_off * data_time_off; // compute load integration time int loadlength = duration(DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // For double phases I can use the added jitterdead in both phases for load int halfloadlength = (loadlength - jitterdead + 1) / 2; // Compare load interval and position switch interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int n_load_on = on_inttime / load_spacing; int n_load_off = off_inttime / load_spacing; // This determines the order of the loops if(load_spacing > 2 * on_inttime) { int n_per_on = n_chop_on; bool end_load_on = false; int on_pointing = on_inttime + jitterdead; } else { n_per_on = n_chop_on / (n_load_on + 1); if(n_per_on < 1) { SError("FS phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * (n_load_on + 1) * data_time; on_pointing = on_inttime + halfloadlength + n_load_on * loadlength + jitterdead; } if(load_spacing > 2 * off_inttime) { int n_per_off = n_chop_off; bool end_load_off = false; int off_pointing = off_inttime + jitterdead; } else { n_per_off = n_chop_off / (n_load_off + 1); if(n_per_off < 1) { SError("FS phase length on OFF position too long relative to load period."); } end_load_off = true; off_inttime = 2 * n_per_off * (n_load_off + 1) * data_time_off; off_pointing = off_inttime + halfloadlength + n_load_off * loadlength + jitterdead; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,true); } initlength = initlength + loadlength; // Compute the overall cycle length // First estimate of the load interval int n_loadinterval = imax(load_interval / (on_pointing + off_pointing),1); // Exception handling for very uneven phases if(end_load_on || end_load_off) { n_loadinterval = 1; } // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {on_inttime,off_inttime,on_pointing,off_pointing,loadlength,jitterdead,load_spacing,n_loadinterval,n_per_on,n_per_off,n_load_on,n_load_off,end_load_on,end_load_off,initlength,dangling}; } /////////////////////////////////////////////// // Generation of messages common to all observing modes // opening for all messages procedure OpenMessages { string modename = "HIFI-Point-PositionSwitch"; // identifier of obsmode {int,int,int,int,int,int,int,int,int,int} seq = {0,0,0,0,0,0,0,0,0,0}; // sequence parameters }{ message(""); message("

Observing mode: " + modename + " executed

"); message("

Sequence parameters

"); message("

"); if(seq{0} != 0) { message("Backend readout period on source: " + seq{0} + "s
"); } if(seq{1} != 0) { message("Backend readout period on OFF: " + seq{1} + "s
"); } if(seq{2} != 0) { message("Number of continuous data dumps per source point: " + seq{2} + "
"); } if(seq{3} != 0) { message("Number of switch cycles on source: " + seq{3} + "
"); } if(seq{4} != 0) { message("Number of cycles on OFF: " + seq{4} + "
"); } if(seq{5} != 0) { message("Number of lines between two OFF measurements: " + seq{5} + "
"); } if(seq{6} != 0) { message("Number of points in one nodding phase: " + seq{6} + "
"); } if(seq{7} != 0) { message("Number of frequencies to combine with one load: " + seq{7} + "
"); } if(seq{8} != 0) { message("Number of pointing cycles: " + seq{8} + "
"); } if(seq{9} != 0) { message("Interval between load measurements: " + seq{9} + "s
"); } message("

"); message("

"); } ///////////////////////////////////////////////////////////////// // Auxiliary routine to determine the two loop phase durations and // the OFF resolution for all FSwitch modes {double,double,double,double} procedure FSwitchPhaseLengths { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF }{ // limits from noise section // resolution of OFF phase double sw_resolution = GetFSwitchSWResolution(band,lo_freq); sw_resolution = max(effResolution{1},sw_resolution); // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); double allan_time_off = allanparms[0] * pow(1.0 / sw_resolution,binningexp); // Differential Allan variance allanparms = InterpolateSpecFSwitchAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // phase lengths double main_phase = 0.3 * dallan_time_lores; double chop_phase = 0.3 * allan_time_lores; double chop_phase_off = 0.3 * allan_time_off; // Constrain by load period int loadper = LoadPeriod(band,lo_freq,effResolution{0}); main_phase = min(main_phase,0.4 * double(loadper)); return {main_phase,chop_phase,chop_phase_off,sw_resolution}; } //Set LCU back to standby status without setting any particular LO band, block //LCU is only set to standby if the band has been switched off block LCU_standby_block_aot HIFI 6629 { }{ {double,string}[] result = ConfigurationReader("name_delays",["stdby_delay"],"0",0.0); int stdby_delay = iround(result[0]{0}); // //Set in standby mode Hifi_HIFI_HL_Standby($BBID); delay(stdby_delay); } {string,double,double}[] procedure HifiSScanModeDBSSequencerInit { string modeName = "freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of DBS modes {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // Get the drift parameters to compute the drift noise // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double} phaselengths = DBSPhaseLengths(band,reffreq,effResolution,continuumDetection,narrowReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // remaining part for n_switch int n_switch_on_guess = iceil(phaselengths{0}) / (n_freq_point_guess * 2 * data_time_guess) + 1; int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } // LCU configuration into NOMINAL mode, procedure procedure LCU_config_nominal_proc_aot { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency }{ //Fetch LO parameters string name_configlo = "name_configlo_a"; string name_configlcu = "name_configlcu_a"; string name_confindex = "name_confindex_a"; string name_configlcutune = "name_configlcutune_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlo = "name_configlo_b"; name_configlcu = "name_configlcu_b"; name_confindex = "name_confindex_b"; name_configlcutune = "name_configlcutune_b"; } // {double,string}[] result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step"],band,lo_freq); double plevel_v = result[0]{0}; double m1_v = result[1]{0}; double m2_v = result[2]{0}; double m3_v = result[3]{0}; int d2_step = iround(result[4]{0}); // double[] cresult = CalibrationReader("name_lcu_safe_values",["g1_v","g2_v","d1_v","d2_v"],band,lo_freq); double gate1_v = cresult[0]; double gate2_v = cresult[1]; double drain1_v = cresult[2]; double drain2_v = cresult[3]; // result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq); int freq_nx = ifloor(result[0]{0}); //Compute lsu_main and offset int[] resu = ComputeLSU_A_M_R(band,lo_freq); int lsu_main = resu[0]; int lsu_offset = resu[1]; //Get checksum result = ConfigurationReader("name_delays",["cus_checksum"],band,lo_freq); int macro_checksum = iround(result[0]{0}); // result = ConfigurationReader(name_configlo,["curlim1_v","curlim2_v"],band,lo_freq); string curlim1_v = result[0]{1}; string curlim2_v = result[1]{1}; // result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq); int config_lo_delay = iround(result[0]{0}); //Fetch best guess result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq); drain2_v = result[0]{0}; //Send command: expect that we have already switched to NOMINAL //We set D2 to best guess and wait some time to stabilize chain temperature HIFI_Configure_LCU_block_aot(band,lo_freq,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum,config_lo_delay); // //TM page dump and error flag clearance now contained in the above block } // common statistics messages procedure PerformanceMessages { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int totaltime = 180; // HIFI time without initial slew double posinttime = 10.0; // Integration time on source double posofftime = 10.0; // Integration time on OFF double timeefficiency = 0.5; // time efficiency double noiseefficiency = 0.125; // noise efficiency double relnoise = 0.01; // drift noise contribution bool reduced = false; // whether deconvolution is assumed }{ // close any previous messages message("

"); message("

Observing mode performance

"); message("

"); // Actual messages message("Observing time without initial slew " + totaltime + "s
"); message("On-source integration time " + posinttime + "s
", 1); message("OFF integration time " + posofftime + "s
", 1); message("Overhead " + (double(totaltime) - posinttime - posofftime) + "s
", 1); message("

"); message("Total time efficiency " + timeefficiency * 100.0 + "%
", 1); message("Total noise efficiency " + noiseefficiency * 100.0 + "%
", 1); message("Drift noise contribution " + relnoise * 100.0 + "%
", 2); message("

"); // Auxiliary explanations - Main beam double fwhm = GetMainBeamSize(band,lo_freq); fwhm = fwhm * 3600.0; double eta_mb = InterpolateCoupling(band,lo_freq); // System temperature is recomputed to be printed without passing double tsys = InterpolateTsys(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); double tsys_lsb = tsys / (eta_mb * gssb[0]); double tsys_usb = tsys / (eta_mb * gssb[1]); message("

"); message("The system noise temperature at " + lo_freq / 1000.0 + " GHz is " + tsys_lsb + " K in the lower and " + tsys_usb + " K in the upper sideband.", 0); message("
"); if(reduced) { message("Deconvolved noise values are given on a two-polarization," + " single-sideband, main beam temperature scale of a " + fwhm + "'' beam with a main beam efficiency of " + eta_mb * 100.0 + "%.", 1); } else { message("All noise values are given on a two-polarization," + " single-sideband, main beam temperature scale of a " + fwhm + "'' beam with a main beam efficiency of " + eta_mb * 100.0 + "%.", 1); } message("

"); message(""); } //Systematic deflux after LO switch-on, procedure procedure Deflux_at_switchon_proc_aot { string band = "4a" in ["ALL","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band. ALL does all bands and all multipliers }{ // } ///////////////////////////////////////////////////////////////// // Second step of timing computation after telescope behaviour // is known - Spectral Scan DBS observing mode // {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},double,double,double} procedure SScanDBS_post_timing { {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = {4,15,4,21,11,1800,22,32,1,false,0,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,20,1,21,0]; int grouplen = 1; int groupnumber = 50; // Total umber of frequency groups int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency bool fastchop = false; // whether fast-chop is used instead of slow-chop }{ // Get all values from the pre_timing section int inttime = pre_timing{0}; int pointing = pre_timing{1}; int readouttime = pre_timing{2}; int loadlength = pre_timing{3}; int jitterdead = pre_timing{4}; int load_spacing = pre_timing{5}; int bigtunestep = pre_timing{6}; int n_loadinterval = pre_timing{7}; int n_bchop = pre_timing{8}; bool end_load = pre_timing{9}; int smallstep = pre_timing{10}; int initlength = pre_timing{11}; int dangling = pre_timing{12}; // Computation for slow-chop or fast-chop if(fastchop) { int readoutperchop = 1; } else { readoutperchop = 2; } // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to OFF int longslew = telescopetimes[4]; // Actual slew time for load slew int pointwaittime = telescopetimes[3]; // Idle time between two phases int tend = telescopetimes[5]; // Final deceleration time ////////////////////////////////////////////////////////////////// // Now we start the actual computations // Pointwaittime is used for tuning // In all non-tuning cycles, pointwaittime acts like a longer slew slewtime = slewtime + pointwaittime; longslew = longslew + pointwaittime; // Half tune step has to be rounded up int halftunestep = (bigtunestep - jitterdead - pointwaittime + 1) / 2; ////////////////////////////////////////////////////////////////////// // Compute timing parameters for the two cases divided by n_cycles > 1 // // Observations with ncycles >1 may be somewhat less efficient // if(n_cycles > 1) { int scan_time = 2 * inttime + slewtime; // How often do I have to perform a load slew // Never switch between short load and long load here if(n_loadinterval > 1) { int old_n_loadinterval = n_loadinterval; n_loadinterval = imax((load_spacing + slewtime) / scan_time,1); // fit with n_cycles n_loadinterval = imin(n_loadinterval,n_cycles); n_loadinterval = IMultiple(n_loadinterval,n_cycles); if(n_loadinterval <= 1) { n_loadinterval = old_n_loadinterval; } } // part of integrations is removed for tuning int n_add = iceil(double(halftunestep) / double(readoutperchop * readouttime)); n_bchop = n_bchop - n_add; if(n_bchop <= 0) { SError("Readout cycle too long relative to nod cycle."); } // Pointing time pointing = inttime + jitterdead; // Average times for noise estimate int shortint = n_bchop * readoutperchop * readouttime; double effinttime = double((n_cycles - 1) * inttime + shortint) / double(n_cycles); int loadpercycle = n_cycles / n_loadinterval; double cycletime = double(2 * pointing) + double(loadpercycle * longslew + (n_cycles - loadpercycle) * slewtime) / double(n_cycles); double avchopnum = double(n_cycles * (n_bchop + n_add) - n_add) / double(n_cycles); // Compute total duration int totaltime = iround(cycletime * double(groupnumber * n_cycles)); } else { // Retuning after each nod cycle // Check group length limited by load_interval scan_time = 2 * (grouplen * inttime + (grouplen - 1) * smallstep) + bigtunestep + slewtime; if(scan_time > load_spacing + slewtime && grouplen > 1) { SError("Frequency group length too large for load interval."); } pointing = grouplen * inttime + (grouplen - 1) * smallstep + halftunestep + jitterdead; // Average times for noise estimate effinttime = double(grouplen * inttime); // ignore the tuning time between cycles cycletime = double(longslew + 2 * pointing - bigtunestep); avchopnum = double(n_bchop); // Compute total duration totaltime = (iround(cycletime) + bigtunestep) * groupnumber; } double tdead = cycletime - 2.0 * effinttime; ////////////////////////////////////////////////////////////////////// // The initial time is no longer contained in the total time initlength = initlength - halftunestep; int shiftlength = halftunestep; // Compute total duration, remove pointwaittime for last slew int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); totaltime = totaltime + dangling - pointwaittime + tend; // show gyro-propagation messages int pointcycle = longslew + 2 * pointing; GCPMessages(pointing,2 * pointcycle,tend); // Return all the times needed in the observing mode modules return {totaltime,{inttime,pointing,readouttime,loadlength,jitterdead,load_spacing,bigtunestep,n_loadinterval,n_bchop,end_load,shiftlength,initlength,dangling},avchopnum,cycletime,tdead}; } ///////////////////////////////////////////////////////////////// // Fast-chop spectral scan observing modes // // Combination of four modules implementing the new structure // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiSScanProcFastDBS { /* Setup parameters */ int naifid = 0; // Tracing object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-SScan-FastChop-DBS",{data_time,0,n_switch_on,n_int_on,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time / 2); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,bool,int,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = FastSScanDBS_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,n_int_on,n_switch_on,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},double,double,double} post_timing = SScanDBS_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int n_loadinterval = post_timing{1}{7}; int n_bchop = post_timing{1}{8}; int shiftlength = post_timing{1}{10}; int initlength = post_timing{1}{11}; double avnumchop = post_timing{2}; // efficiency parameters double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastSScanDBS_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_int_on,n_cycles,n_total,n_bchop,n_switch_on,n_loadinterval,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = FastSScanDBS_deadtimes(band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,n_int_on,n_bchop,n_switch_on,n_cycles,avnumchop,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = SScanDBS_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,continuumDetection,n_cycles,tscan,tact); // Evaluate performance SScanDBS_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_total,groupnumber * n_freq_point,avnumchop * double(n_int_on),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ///////////////////////////////////////////////////////////////// // Fast chop dual beam switch observing mode // // Implemented as procedure returning time and noise levels for HSPOT {string,double,double}[] procedure HifiPointProcFastDBSSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities // Top down approach here int main_phase = iceil(phaselengths{0}); int data_time_guess = 40; int n_switch_on_guess = main_phase / data_time_guess; if(n_switch_on_guess < 2) { n_switch_on_guess = 2; data_time_guess = main_phase / n_switch_on_guess; } // Check with data rate {int,double[]} dataparms = DataTaking(backendreadoutparms,8); int datalimit = 2 * dataparms{0}; if(data_time_guess < datalimit) { data_time_guess = datalimit; n_switch_on_guess = 1; } int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Chop phase length double phase_min = min(max(phaselengths{1},0.15),1.5); int n_int_on_guess = ifloor(double(data_time_guess) / (2.0 * phase_min)); int n_int_on_range = -n_int_on_guess / 2; if(n_int_on_range == 0) { n_int_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)}]; return retvalues; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF observing mode {int,int,int,int,int,int,int,int} procedure OTFmap_pre_timing { int nlines_tot = 1; // Number of rows in the map int npoints = 10; // Number of data dumps per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,5]; // chunk size given by the data rates and optimum speed int n_supersample = 1 in [1,1800]; // Supersamplingfactor int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_intoff = 3 in [1,3600]; // Number of data dumps for the OFF integration time int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); // Is the map size an integer multiple of the scan size? if(nlines_tot == 1) { int n_scans = 1; } else { if(nlines_tot % n_linesperscan != 0) { SError("Map size is no integer multiple of the scan size."); } n_scans = nlines_tot / n_linesperscan; } // Compute parameters for the instrument timing CheckReasonableLineNumber(nlines_tot,true); int n_pp = npoints * n_supersample; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compute parameters for the pointing command int jitterdead = GetMaxTimeJitter(band,lo_freq); int off_inttime = n_intoff * data_time; // OFF integration time int off_pointing = off_inttime + jitterdead; // increase by commanding jitter // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // First estimate of the load interval int scan_time = n_linesperscan * n_pp * data_time + off_pointing; if(scan_time > load_interval) { IError("Scan duration too long for required load period. " + "Reduce the map size or increase the step size."); } int n_loadinterval = imax(load_interval / scan_time,1); n_loadinterval = imin(n_loadinterval,32); // Make sure that load slews occur at the same position in each coverage n_loadinterval = IMultiple(n_loadinterval,n_scans); // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed in the observing mode modules return {n_pp,n_scans,off_inttime,off_pointing,loadlength,n_loadinterval,initlength,dangling}; } procedure HalfFastDBSRaster_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_seq = 1; // number of data transfer cycles per pointing int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles int n_pointsperscan = 1; // Number of points measured before moving to the second pointing phase int n_loadinterval = 10; // number of nods before a load measurement int n_load = 0; // additional load measurements in one pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,0,10,20,21,0,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration bool iscross = false; // Whether we use a cross instead of a raster }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int load_datatime = GetStdLoadReadout(band,lo_freq); // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time / 2); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); // There is no nod counter in the return values - count this by hand int inod = 0; // Do I have to make loads in short nods and subsequent holds? if(iscross) { bool holdforload = n_pointsperscan > 1; } else { holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles; } //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; int[] choppars = [2 * n_int,0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - hkduration - loadlength); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles // The use of n_load differs by 1 from the other observing modes here for(int i1 = 1 .. n_load - 1) { HIFIFastHalfChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastHalfChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: // n_pointsperscan=1, n_loadinterval > n_cycles if(state[3] % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } } // Second pointing phase if(state[0] == 7) { // second nod position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); for(int i2 = 1 .. n_load - 1) { HIFIFastHalfChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFIFastHalfChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: if(state[3] % 2 == 0) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } } // Load nod if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } // Hold if(state[0] == 6) { // finished shift of instrument operations relative to pointing command runintostate = false; } // Final load if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } // Compute the offset between two points // This is an approximation for small offsets {double,double} procedure ApproxAngularOffset { {double,double} vector1 = {0.0,0.0}; // First vector {double,double} vector2 = {0.2,0.2}; // Second vector }{ double pideg = 3.14159265 / 180.0; double fac = cos(0.5 * pideg * (vector1{1} + vector2{1})); return {(vector2{0} - vector1{0}) * fac,vector2{1} - vector1{1}}; } // Procedure to get the instrument boresight string for the used band string procedure GetBoresight { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool chopped = false; // left chopper or center chopper position }{ // Get major number double[] x = CalibrationReader("beam",["beamnumber"],band,lo_freq); int major = iround(x[0]); // Polarization is not used any more - only synthesized beam int bestWbs = 0; // Construct minor number // Frequency: this is coded in the next digit of the beamnumber if(iround(x[0] * 10.0 % 10.0) > 0) { int freqbeam = 1; } else { freqbeam = 0; } // chop angle if(chopped) { int chopbeam = 1; } else { chopbeam = 0; } int minor = bestWbs + 2 * freqbeam + 4 * chopbeam + 1; // Construct finally the boresight string string boresight = "H" + major + minor + "_0"; return boresight; } // Procedure to compute all parameters needed in a Configure_spectroscopy {int,int,int,int,int,int,int,int,int,int,int,int,int} procedure FastConfigureSpectroscopyParams_IST { /* Integration time */ int data_time = 10 in [4,128]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ bool wbs_used = true; // whether at least one WBS is used }{ // Get fixed parameters from configuration and calibration files // WBS delta time given by switch dead time double res = GetSkyChopDeadTime(band,lo_freq); int del_wbs = iceil(res * 1000.0); // Additional delays in the readout loops - given in OBS user manual {double,string}[] result = ConfigurationReader("name_delays",["add_hrs","add_wbs","add_jitter","wbs_readout","wbs_chunksize","tacc_add","max_hrs_phase","wbs_init"],band,lo_freq); int add_hrs = iround(result[0]{0}); int add_wbs = iround(result[1]{0}); int add_jitter = iround(result[2]{0}); int wbs_readout = iround(result[3]{0}); int wbs_chunksize = iround(result[4]{0}); int tacc_add = iround(result[5]{0}); int max_hrs_phase = iround(result[6]{0}); int wbs_init = iround(result[7]{0}); // In fast chop del_hrs can be zero, but see SCR 854 int del_hrs = add_jitter; // WBS // Fixed parameter - we never split a transfer int n_wbs_integr = 1; int n_wbs1 = 2 * n_int; int n_wbs_start = n_data; // HRS is integrated up as long as the WBS int n_hrs_integr = n_int; // Split data_time into chop phases // Dead time per read out (not clear whether add_wbs applies here) int tdead_data = 2 * (wbs_readout + add_jitter) + add_wbs - add_jitter; // Initial dead time - distribute over all readouts int tdead_init = (wbs_init + n_data - 1) / n_data; int chop_phase = (1000 * data_time - tdead_data - tdead_init) / (2 * n_int); // dead time has to be an integer multiple of the 10ms chunk time int tdead_chop = del_wbs + add_jitter; int nchunk = (tdead_chop - 1) / wbs_chunksize + 1; int tcorr = nchunk * wbs_chunksize - tdead_chop; del_wbs = del_wbs + tcorr; tdead_chop = tdead_chop + tcorr; // Accumulation time int t_acc_wbs = chop_phase - tdead_chop; // discretize in 10ms chunks nchunk = (t_acc_wbs - tacc_add) / wbs_chunksize; t_acc_wbs = nchunk * wbs_chunksize + tacc_add; // HRS // Fixed parameter here int r_hrs = 1; int t_acc_hrs = t_acc_wbs - add_jitter - del_hrs - add_hrs; if(t_acc_hrs > max_hrs_phase) { SError("Chop phase length too long for HRS. Increase chop frequency."); } // How many HRS integrations possible during WBS readout int t_hrs_per = t_acc_hrs + del_wbs + add_hrs; int n_hrs_trans = wbs_readout / t_hrs_per; // This currently does not work - SCR 854: skipped n_hrs_trans = 0; // Actual integration time and dead time per readout // If WBS is used count only the WBS time if(wbs_used) { tdead_chop = tdead_chop + tacc_add; int tint_act = nchunk * wbs_chunksize * n_wbs1 * n_data; } else { tdead_chop = tdead_chop + r_hrs * add_hrs; tdead_data = tdead_data + add_jitter - 2 * (n_hrs_trans * t_hrs_per - add_jitter); tint_act = t_acc_hrs * r_hrs * (n_wbs1 + 2 * n_hrs_trans) * n_data; } // Return all config_spectroscopy timing parameters return {n_wbs_start,r_hrs,n_wbs_integr,n_hrs_integr,del_hrs,del_wbs,t_acc_wbs,t_acc_hrs,n_wbs1,n_hrs_trans,tdead_chop,tdead_data,tint_act}; } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure SScanDBS_noisecomputer { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference LO frequency in scan center int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuum = false; // Whether timing is for total-power level int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency double tscan = 60.0; // Total average duration of one scan {double,double,double} tact = {10.0,4.9,0.05}; // Field of actual dead and integration times }{ // spectral scans always use the full bandwidth for reference bool oneGHzReference = false; double tdead = tact{0}; // Average total dead time in one scan double inttimeperphase = tact{1}; // Actual integration time double deadtimeperphase = tact{2}; // Dead time per switch phase // Currently it is not possible to return both drift noise and radiometric // noise so that only their sum is computed. // // Get parameters which are needed double tsys = InterpolateTsys(band,reffreq); double eta_mb = InterpolateCoupling(band,reffreq); double[] gssb = InterpolateGssb(band,reffreq); // Get the drift parameters to compute the drift noise if(continuum) { double[] allanparms = InterpolateTpAllan(band,reffreq,oneGHzReference); } else { allanparms = InterpolateSpecAllan(band,reffreq,oneGHzReference); } // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Differential Allan variance if(continuum) { allanparms = InterpolateTpChopAllan(band,reffreq,oneGHzReference); } else { allanparms = InterpolateSpecChopAllan(band,reffreq,oneGHzReference); } // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double dallan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Compute integration time in one pointing cycle double deadtimeperswitch = deadtimeperphase; double effinttime = (tscan - tdead) / 2.0; // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = DoubleDifferenceNoise(inttimeperphase / allan_time_lores,[1.0,1.0,effinttime / allan_time_lores,effinttime / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); double systemnoise_hires = DoubleDifferenceNoise(inttimeperphase / allan_time_hires,[1.0,1.0,effinttime / allan_time_hires,effinttime / allan_time_hires,deadtimeperswitch / allan_time_hires,tdead / allan_time_hires,alpha,dallan_time_hires / allan_time_hires,dalpha]); double noiseratio = DoubleDifferenceNoiseRatio(inttimeperphase / allan_time_lores,[1.0,1.0,effinttime / allan_time_lores,effinttime / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); // Compute total double sideband noise // Correct for signal in difference phase double dsbnoise_lores = systemnoise_lores / (eff_resolution{1} * 4000000.0 * tscan); double dsbnoise_hires = systemnoise_hires / (eff_resolution{0} * 4000000.0 * tscan); // Divide by n_cycles and number of frequencies double accumulation = double(nfreq * n_cycles); // Compute noise temperature dsbnoise_lores = tsys * sqrt(dsbnoise_lores / accumulation); dsbnoise_hires = tsys * sqrt(dsbnoise_hires / accumulation); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Check for double sideband coverage if(dsb) { // Combine both sidebands // In full spectral scans we have only a combined noise temperature for // both sidebands double usbnoise_lores = dsbnoise_lores / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]); double usbnoise_hires = dsbnoise_hires / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]); double lsbnoise_lores = usbnoise_lores; double lsbnoise_hires = usbnoise_hires; } else { // Get single sideband noise equivalent usbnoise_lores = dsbnoise_lores / gssb[0]; usbnoise_hires = dsbnoise_hires / gssb[0]; lsbnoise_lores = dsbnoise_lores / gssb[1]; lsbnoise_hires = dsbnoise_hires / gssb[1]; } // In spectral scans we have only a combined noise temperature for both // sidebands, so that the USB/LSB separation is not used return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure FastSScanDBS_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int data_time = 4; // chunk size int n_int = 20; // Number of integrations in one readout cycle int n_bchop = 1; // Normal number of chop cycles per frequency and pointing int n_long = 1; // Chop cycles per frequency and pointing without retuning int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency double avnumchop = 1.0; // Average number of chop cycles per frequency double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute parameters for the instrument timing in normal phases {double,double} tinst = GetInstDeadFastChop(data_time,n_int,n_long,band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * n_long) - tinst{0}; // subtract dead times in switches // only half of them are subtracted due to ABAB scheme tdeadint = tdeadint - double(n_int * n_long) * tinst{1}; // treat integration times of other frequencies as dead time double tdeadother = double(data_time * 2 * n_long); // Store double tswitch = tinst{1}; // Integration time double tphaseint = tinst{0}; // Correcton in case of cycles with shorter integrations if(n_cycles > 1) { tinst = GetInstDeadFastChop(data_time,n_int,n_bchop,band,lo_freq,backendreadoutparms); // dead time double tdeadshort = double(data_time * n_bchop) - tinst{0}; // subtract dead times in switches tdeadshort = tdeadshort - double(n_int * n_bchop) * tinst{1}; // weigh tdeadint = (tdeadint * double(n_cycles - 1) + tdeadshort) / double(n_cycles); tphaseint = (tphaseint * double(n_cycles - 1) + tinst{0}) / (2.0 * avnumchop * double(n_cycles) * double(n_int)); tdeadother = (tdeadother * double(n_cycles - 1) + double(data_time * 2 * n_bchop)) / double(n_cycles); } else { tphaseint = tphaseint / (2.0 * avnumchop * double(n_int)); } // Total dead time per cycle double tdead_tot = tdead + double(2 * grouplen) * tdeadint; // Add integration times of other frequencies as dead time tdead_tot = tdead_tot + double(grouplen - 1) * tdeadother; return {tdead_tot,tphaseint,tswitch}; } // Equivalent procedure for configuration parameters following // the master file structure currently used for these calibration files // // This is the generic part used for ILT and AOTs // {double,string}[] procedure FlexibleConfigurationReader { string mainmasterfile = "configuration_masterfile"; // Configuration master file string topicname = "name_confilfpu"; // Name of entry in master file string[] objectnames = ["bias_standby_h"]; // Names of calibration objects to be read string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ // first step: read band master file string masterfile = slookup(mainmasterfile,band,"filename"); // read master file string calibfile = slookup(masterfile,topicname,"value_string"); int dep = ilookup(masterfile,topicname,"dependence"); int readnum = length(objectnames); {double,string}[] retvalues = []; if(dep == 0) { // Quantity is only band dependent // directly read from file looking up the object for(int k = 1 .. readnum) { double dres = dlookup(calibfile,objectnames[k - 1],"value"); string sres = slookup(calibfile,objectnames[k - 1],"value_string"); retvalues[k - 1] = {dres,sres}; } } else { // Quantity is band and frequency dependent // read interpolated value from the data base for(int j = 1 .. readnum) { dres = interpolate(calibfile,objectnames[j - 1],lo_freq); sres = ""; retvalues[j - 1] = {dres,sres}; } } return retvalues; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure SScanLoadChop_commanding { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference characteristic LO frequency {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in both phases double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS tuning levels int data_time = 4; // chunk size int data_time_off = 4; // data dump interval on OFF int n_per_on = 1; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_per_off = 1; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_long_on = 1; // number of cycles on ON without retuning int n_long_off = 1; // number of cycles on OFF without retuning int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency int allsteps = 4; // Total number of frequency pointing periods int n_loadinterval = 1; // number of nods before a load measurement bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int shiftlength = 0; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points // First frequency double runningfreq = freqgrid[grouporder[1][0]]; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] onrates = dataparms{1}; dataparms = DataTaking(backendreadoutparms,data_time_off); double[] offrates = dataparms{1}; int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); // recompute load duration for initial load measurement int loadlength = duration(SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; bool retuneload = n_loadinterval > 1; // Tuning levels string[] targetnames = TargetNames(band,reffreq,retuning,targetlevels); string target = targetnames[0]; // All commands with a duration possibly depending on the frequency // are taken at the reference frequency to guarantee synchonization // Declare auxiliary variables to be used in the loops int i_freqcycles = 0; int i_group = 0; int i_phase = 0; // variables storing the configuration setting bool islong = false; bool isinvalid = true; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // HIFIInitObs(); TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},target); delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 7) { // The NOD-state represents our OFF position // Reset group counter i_group = 0; runintostate = false; // long integrations not possible in last and first PS cycle if(n_cycles > 1 && state[2] % n_cycles != state[2] % 2) { if(isinvalid || !islong) { HIFIConfigureLoadChopIntegration(data_time_off,n_long_off,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFILoadChopOffIntegration(data_time_off,n_long_off,band,reffreq,offrates); } else { if(isinvalid || islong) { HIFIConfigureLoadChopIntegration(data_time_off,n_per_off,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } // No group scanning on OFF HIFILoadChopOffIntegration(data_time_off,n_per_off,band,reffreq,offrates); // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && state[2] % 2 == 0) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[1][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFreq(band,runningfreq,target); runintostate = true; } else { // final load measurement if requested if(final_load) { delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,retuneload,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 1) { isinvalid = true; if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 3) { // The POINT-state represents our source position i_phase = state[2] % 2; // ON integration runintostate = false; // long integrations not possible in last and first nod cycle if(n_cycles > 1 && state[2] % n_cycles != (state[2] % 2 + 1) % 2) { if(isinvalid || !islong) { HIFIConfigureLoadChopIntegration(data_time,n_long_on,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFILoadChopOnIntegration(data_time,n_long_on,band,reffreq,onrates); } else { if(isinvalid || islong) { HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } HIFILoadChopOnIntegration(data_time,n_per_on,band,reffreq,onrates); } // Other frequencies // Reset group counter i_group = 1; if(i_group <= grouplen - 1) { if(isinvalid || islong) { HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } } while(i_group <= grouplen - 1) { // retune runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen]; HIFIChangeFreq(band,runningfreq); HIFILoadChopOnIntegration(data_time,n_per_on,band,reffreq,onrates); i_group = i_group + 1; } // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && i_phase == 1) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[0][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFreq(band,runningfreq,target); runintostate = true; } else { // final load measurement if requested if(final_load) { delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,retuneload,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 0) { isinvalid = true; if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load switch delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,retuneload,eff_resolution{0},data_time,backendreadoutparms); isinvalid = true; runintostate = false; } // Danging load - already covered above // otherwise the instrument stops halftunelength before the telescope if(state[0] == 5) { // finished shift of instrument operations relative to pointing command runintostate = false; HIFICloseObs(); } } } // Configuration for load-chop integration block HIFIConfigureLoadChopIntegration HIFI 6034 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Call procedure doing the work ConfigureSpectroscopy(data_time,2 * n_cycle,"lchop",band,lo_freq,backendreadoutparms); } // Double load chop measurement performed at both frequencies // of a frequency switch observation // Most code is dublicated from normal load measurement // // Most generic version for spectral scans with potentially different // frequencies for tuning and timing and retuning switch // procedure SScanDoubleLoadMeasurement { string band = "4a"; // HIFI band (needed to estimate stabilization) double tuning_freq = 978200.0; // LO tuning frequency double lo_freq = 978200.0; // LO calibration frequency double freq_throw = -40.0; // throw of frequency switch in MHz bool retunelo = true; // Whether LO retuning is enabled double deltanu = 1.0; // minimum effective resolution of the calibrated data int data_time = 4; // time between subsequent data readouts {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Initial computations {int,int,bool} calinit = HIFICalInit(band,lo_freq,deltanu,data_time); int used_datatime = calinit{0}; int n_inttime = calinit{1}; bool retuning = calinit{2} && retunelo; // Perform zero and comb measurement ZeroCombMeasurement(band,lo_freq,used_datatime,backendreadoutparms); // No we perform the actual hot-cold measurement - 2 frequencies int danglingreadout = HIFI_DoubleCalibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,retuning); // Retune and another load if we are in HEB bands if(retuning) { // we have to wait for readout delay(danglingreadout); // Another LO vector scan at the same frequency for a stable HEB operation HIFITuneFreqFsw(band,tuning_freq,tuning_freq + freq_throw,false,""); danglingreadout = HIFI_DoubleCalibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,false); } } // Get standard load read out data cycle used only in fast-chop observations int procedure GetStdLoadReadout { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("stdloadreadout",["loadreadout"],band,lo_freq); return iceil(dead[0]); } ///////////////////////////////////////////////////////////////// // Fast chop dual beam switch observing mode // // The timing is defined as WBS timing, the HRS takes more data during // the WBS read out, but this is ignored in the computations here. // // Combination of four modules implementing the new structure // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiPointProcFastDBS { /* Setup parameters */ int naifid = 0; // Tracing object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-FastChop-DBS",{data_time,0,n_switch_on,n_int_on,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = FastDBS_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} post_timing = DBS_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; bool end_load = post_timing{1}{9}; int shiftlength = post_timing{1}{10}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastDBS_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,n_loadinterval,end_load,final_load,startobs,telescopetimes,loadlength,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = FastDBS_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBS_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_seq * n_int_on * (n_load + 1),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double,double,double} procedure OTFDoubleChop_deadtimes { string chopmode = "chop" in ["chop","lchop","fs"]; // chop mode string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int data_time_off = 4; // data dump interval on OFF int n_switch_on = 1; // Supersamplingfactor int n_switch_off = 3; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_pp = 10; // Number of data dumps per line double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Dead time in OFF {double,double} tinst = GetInstDeadSlowChop(data_time_off,2 * n_switch_off,chopmode,band,lo_freq,backendreadoutparms); // dead time within OFF double tdeadint = double(data_time_off * 2 * n_switch_off) - tinst{0}; // subtract dead times in switches tdeadint = tdeadint - double(n_switch_off) * tinst{1}; // add to total dead time double tdead_tot = tdead + tdeadint; double tswitch_off = tinst{1}; double tphaseint_off = tinst{0} / double(2 * n_switch_off); // Dead time in one line tinst = GetInstDeadSlowChop(data_time,n_pp,chopmode,band,lo_freq,backendreadoutparms); // Dead time for each line tdeadint = double(data_time * n_pp) - tinst{0}; tdead_tot = tdead_tot + double(n_linesperscan) * tdeadint; double tswitch_on = tinst{1}; double tphaseint_on = tinst{0} / double(n_pp); // Return total dead time and actual integration times return {tdead_tot,tphaseint_on,tphaseint_off,tswitch_on,tswitch_off}; } {string,double,double}[] procedure HifiPointModeDBSSequencerInit { string modeName = "dbs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_guess = imax(iceil(phaselengths{0} / (2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)}]; return retvalues; } //////////////////////////////////// // Special DBS raster - cross observing mode // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcDBSCross { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the two raster lines int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-DBS-Cross",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(2,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = custom_map_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSCross_post_timing(pre_timing,telescopetimes,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = custom_map_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int scansize = post_timing{1}{10}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { DBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,true); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,2,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Correct for double counting of central point // The central point noise is returned only double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; noisevalues{4} = noisevalues{4} / multiplier; // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Change LO frequency but keep backend configuration - used in spectral scans // procedure HIFIRetuneFreq { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency ion MHz string level = "sscan_normal"; // Name of target level }{ ConfigureFPU(band,lo_freq,false); HIFITuneFreq(band,lo_freq,true,level); } //Set mixer bias procedure Mixerbias { double bias_h = 0.0; double bias_v = 0.0; }{ Hifi_HIFI_CH1_MXBIAS_V($BBID,bias_h); Hifi_HIFI_CV1_MXBIAS_V($BBID,bias_v); delay(1); } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the OTF observing mode procedure OTFFSwitch_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_perline = 10; // Number of frequency switch cycles per line int n_switch_off = 3; // Number of frequency switch cycles on OFF int nlines_tot = 1; // Total number of lines to scan int n_linesperscan = 1; // Number of lines between two OFFs int n_loadinterval = 1; // number of nods before a load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,2,2,40,10,20,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int toffslew = telescopetimes[6]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] onrates = dataparms{1}; dataparms = DataTaking(backendreadoutparms,data_time_off); double[] offrates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Count OFFs by hand, their counter is not returned in the state array int ioff = 0; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 4) { // OFF Integration HIFIConfigureFSwitchIntegration(data_time_off,n_switch_off,band,lo_freq,backendreadoutparms); HIFIFSwitchOffIntegration(data_time_off,n_switch_off,band,lo_freq,offrates); // OFF counter ioff = ioff + 1; // Check for normal slew after OFF if(state[2] * state[3] < nlines_tot) { HIFIActiveHK("normal",toffslew); } } if(state[0] == 8) { // OTF integration // Check whether we come from the OFF if((state[2] + n_linesperscan - 1) % n_linesperscan == 0) { HIFIConfigureFSwitchIntegration(data_time,n_perline,band,lo_freq,backendreadoutparms); } HIFIFSwitchOnIntegration(data_time,n_perline,band,lo_freq,onrates); // Check for normal slew towards the OFF if(state[2] % n_linesperscan == 0) { if(ioff % n_loadinterval > 0) { HIFIActiveHK("normal",toffslew); } } } if(state[0] == 9) { // Load slew delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 5) { delay(readoutdead); HIFICloseObs(); } } } //////////////////////////////////// // OTF load-chop observing mode without baseline calibration // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcLoadChopOTFNoRef { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-LoadChop-OTF-NoReference",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,bool,int,int} pre_timing = OTFLoadChopNoRef_pre_timing(nlines,npoints_used,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,int} tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,bool,int,int},double,double} post_timing = OTFDoubleChopNoRef_post_timing(pre_timing,telescopetimes,nlines,data_time,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{0}; bool end_load_on = post_timing{1}{4}; int n_loadinterval = post_timing{1}{2}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFLoadChopNoRef_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on,n_loadinterval,nlines * n_cycles,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_switch_on * n_cycles,tscan,tdead); // Evaluate performance OTFDoubleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on * n_cycles,false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {int,double,double,double,double,double} obs HifiMappingModeFSwitchOTFNoRef { string modeName = "fs-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-FSwitch-OTF-NoReference",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,bool,int,int} pre_timing = OTFFSwitchNoRef_pre_timing(nlines,npoints_used,band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,int} tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,bool,int,int},double,double} post_timing = OTFDoubleChopNoRef_post_timing(pre_timing,telescopetimes,nlines,data_time,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{0}; bool end_load_on = post_timing{1}{4}; int n_loadinterval = post_timing{1}{2}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFFSwitchNoRef_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on,n_loadinterval,nlines * n_cycles,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = FSwitchNoRef_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_switch_on * n_cycles,tscan,tdead); // Evaluate performance OTFDoubleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on * n_cycles,true,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //Get diplexer setting using "real" frequencies double[] procedure Get_Diplexer_setting { string band = "3a" in ["3a","3b","4a","4b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 810.0; //LO frequency }{ //Compute real frequency double real_lo_freq = Compute_Real_Freq(band,lo_freq); {double,string}[] result_d = ConfigurationReader("name_confildipl",["diplex_h_a","diplex_v_a","diplex_h_b","diplex_v_b"],band,lo_freq); if(band == "3a" || band == "4a" || band == "6a" || band == "7a") { double[] final_setting = [result_d[0]{0},result_d[1]{0}]; } else { final_setting = [result_d[2]{0},result_d[3]{0}]; } return final_setting; } // Configuration for frequency-switch integration block HIFIConfigureFSwitchIntegration HIFI 6037 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Call procedure doing the work ConfigureSpectroscopy(data_time,2 * n_cycle,"fs",band,lo_freq,backendreadoutparms); } // Normal combination of zero and comb measurement // 1s integration time, only WBS, maximum windows // Inherited from blocks 3604 and 3605 // // Returns dangling transmission time // int block WBS_Zero_Comb HIFI 6004 { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency }{ // Get delays {double,string}[] result = ConfigurationReader("name_delays",["wbs_comb_delay"],band,lo_freq); int wbs_comb_delay = iround(result[0]{0}); // Data rate computation // The HIFI command is restricted to always read out both full WBS {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} fullreadoutparms = FrequencyCalibrationParms(true,true,false,false); // data rate and read-out time {int,double[]} fdataparms = DataTaking(fullreadoutparms,wbs_comb_delay / 2); int readout = fdataparms{0}; // Get attenuators for comb measurement {double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_att_band4_comb","hwh_att_band3_comb","hwh_att_band2_comb","hwh_att_band1_comb","hwh_att_in_comb","hwv_att_band4_comb","hwv_att_band3_comb","hwv_att_band2_comb","hwv_att_band1_comb","hwv_att_in_comb"],band,0.0); int hwh_att_band4 = iround(result_d[0]{0}); int hwh_att_band3 = iround(result_d[1]{0}); int hwh_att_band2 = iround(result_d[2]{0}); int hwh_att_band1 = iround(result_d[3]{0}); int hwh_att_in = iround(result_d[4]{0}); int hwv_att_band4 = iround(result_d[5]{0}); int hwv_att_band3 = iround(result_d[6]{0}); int hwv_att_band2 = iround(result_d[7]{0}); int hwv_att_band1 = iround(result_d[8]{0}); int hwv_att_in = iround(result_d[9]{0}); // // set data rates non_ess_hk_data_rate(fdataparms{1}[2] / 1024.0); data_rate(fdataparms{1}[0] / 1024.0); // Call command Hifi_HIFI_WBS_Comb($BBID,hwh_att_band4,hwh_att_band3,hwh_att_band2,hwh_att_band1,hwh_att_in,hwv_att_band4,hwv_att_band3,hwv_att_band2,hwv_att_band1,hwv_att_in); // Currently I ignore that the COMB ends with ZERO=on (SCR 618) delay(wbs_comb_delay); // reset data rates non_ess_hk_data_rate(fdataparms{1}[1] / 1024.0); data_rate(0.0); // // additional delay for packet transmission before next zero depends // on zero duration - needs to be introduced on higher level return readout; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure DoubleChop_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int n_cycles = 1; // Number of ON-OFF cycles int n_chop_on = 1; // number of half load-sky-sky-load cycles on ON int n_chop_off = 1; // number of half load-sky-sky-load cycles on OFF bool fs = false; // whether frequency switch used double tscan = 60.0; // Total average duration of one scan int pointing = 20; // Pointing duration in the source phase {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; double efficiency = idealnoise / obsnoise; // Compute the actual integration time double posinttime = double(n_cycles * 2 * n_chop_on) * inttimeperonphase; double posofftime = double(n_cycles * 2 * n_chop_off) * inttimeperoffphase; int instrumenttime = iceil(double(n_cycles) * tscan); // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,fs); } ///////////////////////////////////////////////////////////////// // Procedure to filter only those attenuator settings that are used double[][] procedure GetSScanLevelGrid { string band = "4a"; // HIFI band {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} double[] freqgrid = [978053.7,978301.8,978381.1]; // frequency grid int groupnumber = 1; // Number of frequency groups int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in groups }{ // Reduce frequency field - select center frequency of groups only if(groupnumber < length(freqgrid)) { int nfreq = length(freqgrid); double[] redfreq = []; int oldindex = 0; int groupsize = nfreq / groupnumber; // It is not clear whether grouporder[0,0] or grouporder[1,0] // is the better point. First better for DBS, second for NoRef. for(int j1 = 0 .. groupnumber - 1) { oldindex = j1 * groupsize + grouporder[0][0]; redfreq[j1] = freqgrid[oldindex]; } } else { redfreq = freqgrid; } // Make field of subbands that are used int idest = 0; int[] usedsubbands = []; for(int i = 0 .. 3) { if(wbs1{0} && wbs1{1}[i][1] - wbs1{1}[i][0] > 0) { usedsubbands[idest] = i; idest = idest + 1; } } for(int ii = 0 .. 3) { if(wbs2{0} && wbs2{1}[ii][1] - wbs2{1}[ii][0] > 0) { usedsubbands[idest] = ii + 4; idest = idest + 1; } } // Create dB grid needed for backend retuning double[][] retunegrid = GetSScanLevels(band,redfreq,usedsubbands); return retunegrid; } // Interpolate differential frequency switch Allan time and exponent // // This might actually depend on the frequency throw, but no information // is available. Thus a restructuring of this routine is probable. // double[] procedure InterpolateSpecFSwitchAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ if(subband) { double[] allan = CalibrationReader("fs_Allan_subband",["spec_Allan_time","spec_Allan_exp","spec_binning_exp"],band,lo_freq); } else { allan = CalibrationReader("fs_Allan",["spec_Allan_time","spec_Allan_exp","spec_binning_exp"],band,lo_freq); } return allan; } //////////////////////////////////// // Functions for two dimensional vectors, e.g. coordinates on the sky // Multiply a vector defined as a tuple with a scaler defined as a double {double,double} procedure MultiplyScalarVector { double scalar = 1.0; {double,double} vector = {1.0,1.0}; }{ return {vector{0} * scalar,vector{1} * scalar}; } // Interpolate differential sky chop Allan time and exponent double[] procedure InterpolateSpecChopAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ // subband is not used yet double[] allan = CalibrationReader("chop_Allan",["spec_Allan_time","spec_Allan_exp","spec_binning_exp"],band,lo_freq); return allan; } //////////////////////////////////// // OTF observing mode // // Combination of four modules implementing the new structure // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcOTF { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the map center double dec = 0.0; // DEC coordinate of the map center double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,5]; // chunk size given by the data rates and optimum speed int n_int_on = 1 in [1,1800]; // Supersamplingfactor int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-OTF",{data_time,0,n_int_on,0,n_switch_off,n_linesperscan,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,data_time * n_int_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,int,int,int,int} pre_timing = OTFmap_pre_timing(nlines,npoints_used,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_linesperscan,n_switch_off,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_with_off_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int},double,double} post_timing = OTFmap_post_timing(pre_timing,telescopetimes,data_time,n_linesperscan,n_cycles,load_interval); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_with_off_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int n_pp = post_timing{1}{0}; int n_scans = post_timing{1}{1}; int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{5}; double tscan = post_timing{2}; double tdead = post_timing{3}; // telescope time int slewtime = telescopetimes[6]; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFmap_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,nlines * n_cycles,n_linesperscan,n_switch_off,n_pp,n_loadinterval,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check]) int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = OTFmap_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_linesperscan,n_switch_off,n_pp,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = OTFmap_noisecomputer(band,lo_freq,effResolution,oneGHzReference,nlines,npoints_used,n_int_on,n_linesperscan,n_cycles,slewtime,tscan,tact); // Evaluate performance OTF_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_scans,n_cycles,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Get system temperatures for a whole array of frequencies double[] procedure GetAllTsys { string band = "4a"; // HIFI band double[] freqgrid = [978200.0,979600.0]; // Grid of frequencies }{ int nstep = length(freqgrid); double[] tsys = []; for(int i = 0 .. nstep - 1) { tsys[i] = InterpolateTsys(band,freqgrid[i]); } return tsys; } //Procedure to store currently tuned frequency, procedure procedure HIFI_HL_store_tm_proc_fm { }{ Hifi_HIFI_HL_store_tm($BBID); //This commands sends a request to get FSW1/2 into non-periodic HK //Removed as of SPR-1747 //Hifi_HIFI_LCU_macro_buffers(); delay(1); } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of DBS-raster observing mode {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} procedure DBSRaster_post_timing { {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = {4,10,4,21,1,1800,0,10,1,1,1,50,0}; // pre timing parameter list int[] telescopetimes = [300,180,10,0,10,20,21,0,0,0]; int nlines_tot = 1; // Number of rows in the map int npoints = 10; // Number of points per row int n_chop = 2; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800; // load period = f(band,lo_freq,eff_resolution{1}) bool fastchop = false; // whether fast-chop is used instead of slow-chop }{ // Get all values from the pre_timing section int inttime = pre_timing{0}; int pointing = pre_timing{1}; int readouttime = pre_timing{2}; int loadlength = pre_timing{3}; int jitterdead = pre_timing{4}; int load_spacing = pre_timing{5}; int n_load = pre_timing{6}; int n_loadinterval = pre_timing{7}; int n_seq = pre_timing{8}; int n_scans = pre_timing{9}; int scansize = pre_timing{10}; int initlength = pre_timing{11}; int dangling = pre_timing{12}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to next point if(scansize > 1) { int nodtime = telescopetimes[4]; // Slew time to second nod int slewline = telescopetimes[3]; // Slew between lines int longslew = telescopetimes[5]; // Actual slew time for load slew int returntime = telescopetimes[6]; // Idle time between two phases int tend = telescopetimes[7]; // Final deceleration time } else { nodtime = telescopetimes[5]; slewline = telescopetimes[4]; longslew = telescopetimes[6]; returntime = telescopetimes[3]; tend = telescopetimes[9]; } int shortmove = imin(slewtime,slewline); shortmove = imin(shortmove,returntime); // Total number of scans int n_tot = n_scans * n_cycles; /////////////////////// // Long computation for scansize > 1 to obtain all slew durations {int,int} alldeadtimes = Raster_slewtimes(nlines_tot,npoints,n_cycles,scansize,nodtime,slewtime,slewline,returntime); int tinscandead = alldeadtimes{0}; int toutscandead = alldeadtimes{1}; // Compute total duration of measurement and average scan length int totalscantime = n_tot * (2 * pointing * scansize) + tinscandead; // approximate scan time for load comparison int scan_time = iceil(double(totalscantime) / double(2 * n_tot)); if(load_spacing > 2 * scan_time) { n_seq = n_chop; pointing = inttime + jitterdead; bool end_load = false; } else { // It could happen that the slew extends the scan too much - catch if(scansize > 1) { SError("Number of points in one scan too large for load period."); } n_load = n_load + 1; n_seq = n_chop / n_load; if(n_seq < 1) { SError("Transfer cycle too long relative to load period."); } // adjust pointing time to include load measurements int loadappend = imax(loadlength - shortmove,0); end_load = true; // Computation for slow-chop or fast-chop if(fastchop) { inttime = n_seq * n_load * readouttime; } else { inttime = 2 * n_seq * n_load * readouttime; } pointing = inttime + loadappend + (n_load - 1) * loadlength + jitterdead; } totalscantime = n_tot * (2 * pointing * scansize) + tinscandead + toutscandead; scan_time = iceil(double(totalscantime) / double(2 * n_tot)); // compute the load interval in case of short scan_time n_loadinterval = imax((load_interval - loadlength + nodtime) / (2 * scan_time),1); // Special treatment for nodding_raster due to limitations in API // Split into loads per point or per multiple points if(scansize == 1 && n_loadinterval > n_cycles) { n_loadinterval = n_cycles * (n_loadinterval / n_cycles); // Translate load waiting time into a hold after the point int holdlength = imax(loadlength - nodtime,0); longslew = nodtime + holdlength; } else { holdlength = 0; } // Special treatment for loads per point to compensate counter reset if(scansize == 1 && n_loadinterval < n_cycles) { int dangling_period = n_cycles % n_loadinterval; while((dangling_period + n_loadinterval) * 2 * scan_time > load_interval - loadlength + nodtime) { n_loadinterval = n_loadinterval - 1; dangling_period = n_cycles % n_loadinterval; } // Consistency check if(n_loadinterval < 1) { CError("Too short load period computed."); } int n_long = n_scans * (n_cycles / n_loadinterval); } else { n_long = n_tot / n_loadinterval; } // Compute total duration of measurement, correct for load nods totalscantime = n_tot * (2 * pointing * scansize) + tinscandead + n_long * (longslew - nodtime); // Average dead and scan time for drift estimate double tscan = double(totalscantime) / double(n_tot); double tdead = tscan - double(2 * inttime * scansize); // Count integration times of other points of one nod as dead time // Other points in the second nod are excluded from the scan double othertime = double((scansize - 1) * inttime); tdead = tdead + othertime; // Reduce scan time by the other points in the second nod phase tscan = tscan - othertime; // Determine need for final load measurement double rest = double(n_tot % n_loadinterval) + 0.5; bool final_load = rest > 0.5001 * double(n_loadinterval); // Compute total duration // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int totaltime = totalscantime + toutscandead; // Add dangling load time if not included in pointing // they are mutually exclusive, otherwise the readoutdelay applies if(final_load) { dangling = loadlength; } if(end_load) { dangling = loadlength - loadappend; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); totaltime = totaltime + dangling + tend; // show gyro-propagation messages if(scansize > 1) { GCPMessages(0,totalscantime,tend); } else { GCPMessages(pointing,totalscantime,tend); } // Return all the times needed in the observing mode modules return {totaltime,{inttime,pointing,readouttime,loadlength,holdlength,load_spacing,n_load,n_loadinterval,n_seq,n_scans,scansize,initlength,dangling},final_load,tscan,tdead}; } // Procedure to compute all parameters needed in a Configure_spectroscopy // This is a special version for IST, not to be used in normal AOTs // see HIFI SCRs 1029 and 1483 {int,int,int,int,int,int,int,int,int,int} procedure ConfigureSpectroscopyParams_IST { /* Integration time */ int data_time = 4; // Integration time between two data readouts int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string chopmode = "chop" in ["chop","lchop","fs","hot-cold","tp","chopcal"]; // Chop mode determining the modulation dead time string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used,channel windows} }{ // Get fixed parameters from configuration and calibration files // Command jitter time is the default delay {double,string}[] result = ConfigurationReader("name_delays",["add_jitter"],band,lo_freq); int add_jitter = iround(result[0]{0}); // WBS delta time // Default total power. This should be 0. int del_wbs = add_jitter; // WBS delta time given by switch dead time if(chopmode == "chop") { double res = GetSkyChopDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "lchop") { res = GetLoadChopDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "fs") { res = GetFSwitchDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "chopcal") { res = GetHotColdDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "hot-cold") { bool wbsused = backendreadoutparms{2}{0} || backendreadoutparms{3}{0}; res = HotColdRelaxTime(band,lo_freq,wbsused); del_wbs = iceil(res * 1000.0); } // HRS delta time - should be zero as well int del_hrs = add_jitter; // Additional delays in the readout loops - given in OBS user manual result = ConfigurationReader("name_delays",["add_hrs","add_wbs","add_jitter","wbs_init","wbs_chunksize","tacc_add","hrs_phase","min_wbs_acc","stdchop_phase"],band,lo_freq); int add_hrs = iround(result[0]{0}); int add_wbs = iround(result[1]{0}); int wbs_init = iround(result[3]{0}); int wbs_chunksize = iround(result[4]{0}); int tacc_add = iround(result[5]{0}); int hrs_phase = iround(result[6]{0}); // HRS standard phase length int min_wbs_acc = iround(result[7]{0}); // WBS transfer time int stdchopphase = iround(result[8]{0}); // Split total integration time int tint = data_time * n_data * 1000; int n_wbs_integr = data_time * 1000 / stdchopphase; // dead time has to be an integer multiple of the 10ms chunk time int tdead = del_wbs + add_wbs + add_jitter; int nchunk = (tdead - 1) / wbs_chunksize + 1; int tcorr = nchunk * wbs_chunksize - tdead; del_wbs = del_wbs + tcorr; tdead = tdead + tcorr; // Accumulation time // Ignores that total power can be slightly more efficient int t_acc_wbs = (tint - wbs_init) / (n_data * n_wbs_integr) - tdead; // discretize in 10ms chunks nchunk = (t_acc_wbs - tacc_add) / wbs_chunksize; t_acc_wbs = nchunk * wbs_chunksize + tacc_add; // Check relative to minimum accumulation tim if(t_acc_wbs + del_wbs + add_wbs < min_wbs_acc + add_jitter) { SError("WBS integration too short for readout. Increase duration."); } int n_wbs_start = n_data * n_wbs_integr; // HRS int hrs_fullphase = hrs_phase + del_hrs + add_hrs; int r_hrs = (t_acc_wbs + hrs_fullphase - add_jitter) / hrs_fullphase; int t_acc_hrs = (t_acc_wbs - add_jitter) / r_hrs - del_hrs - add_hrs; // for n_wbs_integr=1 identical to r_hrs int n_hrs_integr = r_hrs * n_wbs_integr; // Compute actual integration time and dead time per readout // If WBS is used count only the WBS time if(backendreadoutparms{2}{0} || backendreadoutparms{3}{0}) { int tint_act = nchunk * wbs_chunksize * n_data * n_wbs_integr; tdead = tdead + tacc_add; } else { tint_act = t_acc_hrs * r_hrs * n_data * n_wbs_integr; tdead = tdead + r_hrs * (del_hrs + add_hrs) + add_jitter; } // Return all config_spectroscopy timing parameters return {n_wbs_start,r_hrs,n_wbs_integr,n_hrs_integr,del_hrs,del_wbs,t_acc_wbs,t_acc_hrs,tdead,tint_act}; } // Rotate angle by -90 deg double procedure RotateRight { double angle = 0.0; // Original angle }{ double fullcircle = 360.0; return (angle + fullcircle * 0.75) % fullcircle; } // General version used in non-spectral scan FSW modes procedure DoubleLoadMeasurement { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency double freq_throw = -40.0; // throw of frequency switch in MHz double deltanu = 1.0; // minimum effective resolution of the calibrated data int data_time = 4; // time between subsequent data readouts {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Call generic version with fixed parameters SScanDoubleLoadMeasurement(band,lo_freq,lo_freq,freq_throw,true,deltanu,data_time,backendreadoutparms); } // Get dead time for chopper motion between HBB and CBB double procedure GetHotColdDeadTime { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("hotcold_deadtime",["hotcold"],band,lo_freq); return dead[0]; } ///////////////////////////////////////////////////////////////// // Auxiliary routine to determine the two loop phase durations and // the OFF resolution for all load-chop modes {double,double,double,double} procedure LoadChopPhaseLengths { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF }{ // limits from noise section // resolution of OFF phase double sw_resolution = GetLoadChopSWResolution(band,lo_freq); sw_resolution = max(effResolution{1},sw_resolution); // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); double allan_time_off = allanparms[0] * pow(1.0 / sw_resolution,binningexp); // Differential Allan variance allanparms = InterpolateSpecLChopAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // phase lengths double main_phase = 0.3 * dallan_time_lores; double chop_phase = 0.3 * allan_time_lores; double chop_phase_off = 0.3 * allan_time_off; // Constrain by load period int loadper = LoadPeriod(band,lo_freq,effResolution{0}); main_phase = min(main_phase,0.4 * double(loadper)); return {main_phase,chop_phase,chop_phase_off,sw_resolution}; } //////////////////////////////////// // Peakup observing mode // obs HifiEngPeakup { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string backend = "WBS" in ["WBS","HRS"]; // backend to use - resolution string polarization = "H" in ["H","V"]; // backend to use - polarization }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = PeakupBackendSettings(backend,polarization,band,lo_freq,1); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; // Call first part of the timing computer {int,int,int,int,int,double,int,int} pre_timing = Peakup_pre_timing(3,3,band,lo_freq,hr1,hr2,wb1,wb2); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double} tpar = Peakup_telescope(naifid,onPosition,stepsize,3,3,band,lo_freq,pre_timing); int[] telescopetimes = basic_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,double,int,int}} post_timing = Peakup_post_timing(pre_timing,telescopetimes,3,3); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = Peakup_telescope(naifid,onPosition,stepsize,3,3,band,lo_freq,post_timing{1}); telescopetimes = basic_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int data_time = post_timing{1}{2}; int n_int = post_timing{1}{4}; double eff_resolution = post_timing{1}{5}; int initlength = post_timing{1}{6}; int dangling = post_timing{1}{7}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); /////////////////////////////////////////////////////////////////////// // Call instrument commands Peakup_commanding(band,lo_freq,hr1,hr2,wb1,wb2,data_time,n_int,eff_resolution,stepsize,startobs,telescopetimes,loadlength); // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } } // WBS stand-by, block block WBS_standby_block_aot HIFI 6703 { string laser = "ON" in ["ON","OFF"]; //laser status: if ON, read from configwbs.config }{ //Set zero ON Hifi_HIFI_switch_zero_WBS_H($BBID,"ON"); Hifi_HIFI_switch_zero_WBS_V($BBID,"ON"); delay(1); //Standby configuration //H-Polarization // {double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s"],"0",0.0); string hwh_laser1_s = result_d[0]{1}; string hwh_laser2_s = result_d[1]{1}; if(laser == "OFF") { hwh_laser1_s = "OFF"; hwh_laser2_s = "OFF"; } int hwh_heater = iround(result_d[2]{0}); string hwh_latchup_s = result_d[3]{1}; // int hwh_att_band4 = 7; int hwh_att_band3 = 7; int hwh_att_band2 = 7; int hwh_att_band1 = 7; int hwh_att_in = 15; // //Configure WBS-H Hifi_HIFI_Configure_WBS_H($BBID,hwh_laser1_s,hwh_laser2_s,hwh_heater,hwh_latchup_s,hwh_att_band4,hwh_att_band3,hwh_att_band2,hwh_att_band1,hwh_att_in); {double,string}[] result = ConfigurationReader("name_delays",["wbs_config_delay"],"0",0.0); int wbs_config_delay = iround(result[0]{0}); //delay(wbs_config_delay); //Wait for configuration to be applied // //V-Polarization // result_d = ConfigurationReader("name_configwbs",["hwv_laser1_s","hwv_laser2_s","hwv_heater","hwv_latchup_s"],"0",0.0); string hwv_laser1_s = result_d[0]{1}; string hwv_laser2_s = result_d[1]{1}; if(laser == "OFF") { hwv_laser1_s = "OFF"; hwv_laser2_s = "OFF"; } int hwv_heater = iround(result_d[2]{0}); string hwv_latchup_s = result_d[3]{1}; // int hwv_att_band4 = 7; int hwv_att_band3 = 7; int hwv_att_band2 = 7; int hwv_att_band1 = 7; int hwv_att_in = 15; // //Configure WBS-V Hifi_HIFI_Configure_WBS_V($BBID,hwv_laser1_s,hwv_laser2_s,hwv_heater,hwv_latchup_s,hwv_att_band4,hwv_att_band3,hwv_att_band2,hwv_att_band1,hwv_att_in); delay(wbs_config_delay); //Wait for configuration to be applied // } //////////////////////////////////////////////////// // Building blocks used in general observations // // They call procedures which should be common between ILT and space // Actual building blocks possible when numbers are // assigned. // // Currently, these blocks contain the data rate computations. ///////////////////////////////////////////////////////////////////////////// // Collection of identical procedures for continuous data read out // calling different building blocks to make data distinguisable // Set observation ID for the current observation - start of every obs block HIFIInitObs HIFI 6000 { }{ // new delay to allow for insertion of BUSCONFIG by MPS // email from Larry, October 19, 2007 // applies only to RMS and SOVT - removed again in HSPOT version // delay(1); // Set ObsId as very first step Hifi_HIFI_Set_OBS_ID($BBID,$OBSID); } ///////////////////////////////////////////////////////////////// // Stability parameters // Interpolate system Allan time and exponent for the selected frequency double[] procedure InterpolateSpecAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ if(subband) { double[] allan = CalibrationReader("system_Allan_subband",["spec_Allan_time","spec_Allan_exp","spec_binning_exp"],band,lo_freq); } else { allan = CalibrationReader("system_Allan",["spec_Allan_time","spec_Allan_exp","spec_binning_exp"],band,lo_freq); } return allan; } // Drift noise from an OTF sequence // This is still to be scaled by a factor 1.0/(B_fluct*T_A) double procedure OtfDrift { double x = 0.02; // integration time (everything relative to the Allan time) double xr = 0.06; // reference integration time double d1 = 0.3; // time difference between last OFF and point double d2 = 0.3; // time difference between point and next OFF double alpha = 2.5; // drift exponent }{ if(x > 0.0) { // Auxiliary quantities for computation double b1 = alpha - 1.0; double a1 = alpha + 1.0; double l = (d2 + 0.5 * (xr + x)) / (d1 + d2 + xr + x); double ladd = 1.0 - 2.0 * l + 2.0 * l * l; double xi = d1 + d2 + x; // tscan // Now the drift noise variance double y = (-pow(x,b1) - ladd * pow(xr,b1) - l * (1.0 - l) * (pow(2.0 * xr + xi,a1) - 2.0 * pow(xr + xi,a1) + pow(xi,a1)) / (xr * xr) + l * (pow(x + xr + d1,a1) - pow(xr + d1,a1) - pow(x + d1,a1) + pow(d1,a1)) / (xr * x) + (1.0 - l) * (pow(x + xr + d2,a1) - pow(xr + d2,a1) - pow(x + d2,a1) + pow(d2,a1)) / (xr * x)) / (pow(2.0,alpha) - 2.0); } else { // forbid x values <=0 y = 1.0E11 * (1.0 - x); } return y; } ///////////////////////////////////////////////////////////////// // Routines using the generic reader // A possible frequency dependence is hidden behind the reader ///////////////////////////////////////////////////////////////// // Interpolate system temperature for the selected frequency // System temperature is always double sideband system temperature double procedure InterpolateTsys { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] tsys = CalibrationReader("tsys",["tsys_h","tsys_v"],band,lo_freq); double combined = 1.0 / (tsys[0] * tsys[0]) + 1.0 / (tsys[1] * tsys[1]); return 1.0 / sqrt(combined); } // Get number which is an integer multiple or divisor int procedure IMultiple { int i = 1; // input variable int n = 10; // field size }{ int retval = imax(i,1); if(i > n) { retval = n * (i / n); } else { while(n % retval != 0) { retval = retval - 1; } } return retval; } // Perform load chop integration at ON position block HIFILoadChopOnIntegration HIFI 6035 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_cold","chop_M3"],rates); } // Fast-chop procedure HIFI_Spectr_fast_chop_proc_aot { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // readout cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string[] phases = ["chop_M3left","chop_M3right"]; // identifiers for chopper positions int[] parms = [1,0]; // Parameters for chop cycles double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ //Get appropriate chopper voltages {bool,double,double} chopparms = GetChopVoltages(band,lo_freq,phases[0],phases[1]); bool isPrime = chopparms{0}; // set data rates non_ess_hk_data_rate(rates[2] / 1024.0); data_rate(rates[0] / 1024.0); // Call command if(isPrime) { Hifi_HIFI_P_Spectr_fast_chop($BBID,chopparms{1},chopparms{2},parms[0],parms[1]); } else { Hifi_HIFI_R_Spectr_fast_chop($BBID,chopparms{1},chopparms{2},parms[0],parms[1]); } delay(n_cycle * data_time); // reset data rates non_ess_hk_data_rate(rates[1] / 1024.0); data_rate(0.0); } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure FastSScanDBS_commanding { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference characteristic LO frequency {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in both phases double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS tuning levels int data_time = 10; // data dump interval int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency int allsteps = 4; // Total number of frequency pointing periods int n_bchop = 1; // Normal number of chop cycles per frequency and pointing int n_long = 1; // Chop cycles per frequency and pointing without retuning int n_loadinterval = 1; // number of nods before a load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int shiftlength = 10; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points // First frequency double runningfreq = freqgrid[grouporder[0][0]]; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time / 2); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,true); int readoutdead = FastChopReadoutDelay(band,reffreq,backendreadoutparms); // recompute load duration for initial load measurement int load_datatime = GetStdLoadReadout(band,reffreq); int loadlength = duration(SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},load_datatime,backendreadoutparms)); loadlength = loadlength + readoutdead; bool retuneload = n_loadinterval > 1; // Tuning levels string[] targetnames = TargetNames(band,reffreq,retuning,targetlevels); string target = targetnames[0]; // All commands with a duration possibly depending on the frequency // are taken at the reference frequency to guarantee synchonization // Declare auxiliary variables to be used in the loops int i_freqcycles = 0; int i_group = 0; int i_phase = 0; int[] choppars = [1,0]; // variables storing the configuration setting bool islong = false; bool isinvalid = true; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // HIFIInitObs(); TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},target); delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},load_datatime,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position i_phase = (state[2] + 1) % 2; // Reset group counter i_group = 0; runintostate = false; // long integrations not possible in last and first nod cycle if(n_cycles > 1 && state[2] % n_cycles != state[2] % 2) { if(isinvalid || !islong) { choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_long,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFIFastChopOnIntegration(data_time,n_long,band,reffreq,choppars,rates); } else { if(isinvalid || islong) { choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_bchop,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } while(i_group < grouplen - 1) { HIFIFastChopOnIntegration(data_time,n_bchop,band,reffreq,choppars,rates); // retune i_group = i_group + 1; runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen]; HIFIChangeFreq(band,runningfreq); } HIFIFastChopOnIntegration(data_time,n_bchop,band,reffreq,choppars,rates); // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && i_phase == 1) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[0][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFreq(band,runningfreq,target); runintostate = true; } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 1 && state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } if(state[0] == 7) { // second nod position i_phase = state[2] % 2; // First nodding position // Reset group counter i_group = 0; runintostate = false; // long integrations not possible in last and first nod cycle if(n_cycles > 1 && state[2] % n_cycles != (state[2] % 2 + 1) % 2) { if(isinvalid || !islong) { choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_long,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFIFastChopOffIntegration(data_time,n_long,band,reffreq,choppars,rates); } else { if(isinvalid || islong) { choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_bchop,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } while(i_group < grouplen - 1) { HIFIFastChopOffIntegration(data_time,n_bchop,band,reffreq,choppars,rates); // retune i_group = i_group + 1; runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen]; HIFIChangeFreq(band,runningfreq); } HIFIFastChopOffIntegration(data_time,n_bchop,band,reffreq,choppars,rates); // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && i_phase == 1) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[0][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFreq(band,runningfreq,target); runintostate = true; } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 0 && state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } if(state[0] == 9) { // Load nod delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,retuneload,eff_resolution{0},load_datatime,backendreadoutparms); isinvalid = true; runintostate = false; } if(state[0] == 5) { // The instrument stops halftunelength before the telescope // but I have to wait to close the observation HIFICloseObs(); } } } // Get frequency resolution needed to measure standing wave pattern // in frequency switch measurements // // This might actually depend on the frequency throw, but no information // is available. Thus a restructuring of this routine is probable. // double procedure GetFSwitchSWResolution { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("fsswresolution",["resolution"],band,lo_freq); return dead[0]; } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for the mode // {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double} procedure PositionSwitch_post_timing { {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing = {12,12,13,13,21,11,1800,32,1,1,0,0,false,false,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,20,1,21,0]; int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF cycles }{ // Get all values from the pre_timing section int inttime = pre_timing{0}; int pointing = pre_timing{2}; int loadlength = pre_timing{4}; int halfloadlength = pre_timing{5}; int load_spacing = pre_timing{6}; int n_loadinterval = pre_timing{7}; bool final_load = pre_timing{12}; int initlength = pre_timing{14}; int dangling = pre_timing{15}; // dummy parameters int n_seq = pre_timing{8}; int n_load = pre_timing{10}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to OFF int longslew = telescopetimes[4]; // Actual slew time for load slew int pointwaittime = telescopetimes[3]; // Idle time between two phases int tend = telescopetimes[5]; // Final deceleration time // treat pointwaittime like an additional slew dead time in cycles slewtime = slewtime + pointwaittime; longslew = longslew + pointwaittime; // Now we can compute the true scan time int scan_time = 2 * pointing + slewtime; // Check for reasonable scan times if(scan_time > load_spacing + slewtime) { SError("Phase length too long relative to load period."); } // Finally I can compute the true load interval n_loadinterval = imax((load_spacing + slewtime) / scan_time,1); // Compute duration of measurement and average scan length // Compute total dead time in one pointing cycle including load overhead int scan_time_long = 2 * pointing + longslew; int n_long = n_cycles / n_loadinterval; int looplength = (n_cycles - n_long) * scan_time + n_long * scan_time_long; double tscan = double(looplength) / double(n_cycles); // Get pointing dead time, instrument dead time is added later double tdead = tscan - double(2 * inttime); // Determine need for final load measurement double rest = double(n_cycles % n_loadinterval) + 0.5; final_load = rest > 0.5001 * double(n_loadinterval); // Add dangling load time if(final_load) { dangling = loadlength; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute total duration, remove pointwaittime for last slew // The initial time is no longer contained in the total time //int totaltime=imax(initlength,telinit); int totaltime = looplength + dangling - pointwaittime + tend; // show gyro-propagation messages GCPMessages(pointing,2 * scan_time_long,tend); // Return all the times needed in the telescope and instrument modules return {totaltime,{inttime,inttime,pointing,pointing,loadlength,halfloadlength,load_spacing,n_loadinterval,n_seq,n_seq,n_load,n_load,final_load,final_load,initlength,dangling},tscan,tdead}; } // Procedure to compute detailed pre timing for the version of the // load chop mode used in LO switch-on {int,int,int,int,int,int} procedure SwitchOnLoadChop_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rates bool spectrChop = true; // whether the subsequent AOR is chopped+spectroscopic }{ // Determine parameters of stabilization observation // Get total stabilization time determining the duration of the mode if(spectrChop) { string stabilization = "stabilize_chop"; } else { stabilization = "stabilize_ps"; } double[] tunewait = CalibrationReader("tunetime",[stabilization,"retunelo"],band,lo_freq); int modelength = iceil(tunewait[0]); int retuneinterval = iceil(tunewait[1]); // Normal load-chop-noref pre_timing // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); int jitterdead = GetMaxTimeJitter(band,lo_freq); // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Duration of initial set up int initlength = duration(HIFIInitObs()); // Add time for HK readout int hkduration = duration(HIFISetHK("normal",false)); initlength = initlength + 2 * hkduration; // Get time for actual LO switch-on initlength = initlength + duration(LCU_switchon_proc_aot(band,lo_freq / 1000.0)); // Times for additional actions after LO switch on int addinitlength = loadlength; // Add time for Mixer setup, LO tuning, Deflux addinitlength = addinitlength + duration(Init_Mixing_proc_aot(band,lo_freq / 1000.0)) + duration(Deflux_SingleBand_proc_aot(band,lo_freq / 1000.0)); // Add times for backend tuning string target_name = "normal"; if(wbs1{0} || wbs2{0}) { addinitlength = addinitlength + duration(WBS_attenuators_block(band,lo_freq / 1000.0,target_name,false)); } if(hrs1{0} || hrs2{0}) { addinitlength = addinitlength + duration(HRS_tune_block_aot(band)); } // increase initialization time by additional actions, reduce measurement time initlength = initlength + addinitlength; modelength = modelength - addinitlength; // Second step - LO retuning after 5 minutes if covered int retuneduration = duration(HIFITuneFreq(band,lo_freq,false,"")); if(modelength + addinitlength > retuneinterval) { int modelength1 = imax(retuneinterval - retuneduration - addinitlength,0); int n_cycles1 = imax(modelength1 / (2 * data_time),1); // Get number of cycles needed to cover waiting time modelength = modelength - modelength1 - retuneduration; int n_cycles = imax(modelength / (2 * data_time),1); // Compute parameters for the instrument timing int on_inttime = 2 * (n_cycles + n_cycles1) * data_time + retuneduration + readoutdead; int on_pointing = on_inttime + imax(readoutdead,jitterdead); } else { n_cycles1 = 0; n_cycles = imax(modelength / (2 * data_time),1); on_inttime = 2 * n_cycles * data_time; on_pointing = on_inttime + imax(readoutdead,jitterdead); } // Compute total times int looplength = on_pointing; // dangling load time int dangling = loadlength; int closelength = duration(HIFICloseObs()); dangling = dangling + closelength; // Compute total duration int totaltime = initlength + looplength + dangling; // return resorted data set return {totaltime,on_pointing,initlength,dangling,n_cycles1,n_cycles}; } // Compute the integration time required on the thermal loads int procedure LoadIntegrationTime { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency double deltanu = 1.0; // minimum effective resolution of the calibrated data }{ // get load temperatures {double,double} loadtemp = LoadTemperatures(band,lo_freq); double t_hot = loadtemp{0}; double t_cold = loadtemp{1}; double t_sys = InterpolateTsys(band,lo_freq); // compare to load period int loadperiod = LoadPeriod(band,lo_freq,deltanu); // exception handling for zero frequency resolutions if(deltanu < 0.01) { int intload = loadperiod / 8; } else { // estimator equation guaranteeing only 1% error from load calibration double tload = 0.01 / deltanu * ((t_hot + t_sys) * (t_hot + t_sys) + (t_cold + t_sys) * (t_cold + t_sys)) / ((t_hot - t_cold) * (t_hot - t_cold)); intload = iceil(tload); // never exceed half of the load period, even for FSwitch intload = imin(intload,loadperiod / 8); } return intload; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double,double,double} procedure SScanDoubleChop_deadtimes { string chopmode = "chop" in ["chop","lchop","fs"]; // chop mode string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int data_time = 4; // data dump interval on ON int data_time_off = 4; // data dump interval on OFF int n_chop_on = 3; // number of chop cycles in one integration on ON int n_chop_off = 3; // number of chop cycles in one integration on OFF int n_long_on = 3; // number of chop cycles for long integration on ON int n_long_off = 3; // number of chop cycles for long integration on OFF int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency double avnumchop_on = 1.0; // Average number of ON chop cycles per frequency double avnumchop_off = 1.0; // Average number of OFF chop cycles per frequency double tscan = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute parameters for the instrument timing in normal phases // Four different cases involved {double,double} tinst = GetInstDeadSlowChop(data_time,2 * n_chop_on,chopmode,band,lo_freq,backendreadoutparms); // dead time double tdeadint_on = double(data_time * 2 * n_chop_on) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdeadint_on = tdeadint_on - double(n_chop_on) * tinst{1}; // treat integration times of other frequencies as dead time double tdeadother = double(data_time * 2 * n_chop_on); // Store double tswitch_on = tinst{1}; // Integration time double tphaseint_on = tinst{0}; // Correcton in case of cycles with longer integrations if(n_cycles > 1) { tinst = GetInstDeadSlowChop(data_time,2 * n_long_on,chopmode,band,lo_freq,backendreadoutparms); // dead time double tdeadlong = double(data_time * 2 * n_long_on) - tinst{0}; // subtract dead times in switches tdeadlong = tdeadlong - double(n_long_on) * tinst{1}; // weigh int numlong_on = 2 * (n_cycles / 2); double wlong = double(numlong_on) / double(grouplen * n_cycles); double wshort = double(n_cycles * grouplen - numlong_on) / double(grouplen * n_cycles); tdeadint_on = wlong * tdeadlong + wshort * tdeadint_on; tphaseint_on = (wlong * tinst{0} + wshort * tphaseint_on) / (2.0 * avnumchop_on); tdeadother = wshort * tdeadother + double(data_time * 2 * n_long_on) * wlong; } else { tphaseint_on = tphaseint_on / (2.0 * avnumchop_on); } // OFF phase tinst = GetInstDeadSlowChop(data_time_off,2 * n_chop_off,chopmode,band,lo_freq,backendreadoutparms); // dead time double tdeadint_off = double(data_time_off * 2 * n_chop_off) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdeadint_off = tdeadint_off - double(n_chop_off) * tinst{1}; // Store double tswitch_off = tinst{1}; // Integration time double tphaseint_off = tinst{0}; // Correcton in case of cycles with longer integrations if(n_cycles > 1) { tinst = GetInstDeadSlowChop(data_time_off,2 * n_long_off,chopmode,band,lo_freq,backendreadoutparms); // dead time tdeadlong = double(data_time_off * 2 * n_long_off) - tinst{0}; // subtract dead times in switches tdeadlong = tdeadlong - double(n_long_off) * tinst{1}; // weigh int numlong_off = 2 * ((n_cycles - 1) / 2); wlong = double(numlong_off) / double(n_cycles); wshort = double(n_cycles - numlong_off) / double(n_cycles); tdeadint_off = wlong * tdeadlong + wshort * tdeadint_off; tphaseint_off = (wlong * tinst{0} + wshort * tphaseint_off) / (2.0 * avnumchop_off); } else { tphaseint_off = tphaseint_off / (2.0 * avnumchop_off); } // Total dead time per cycle double tdead = tscan - double(grouplen * 2 * data_time) * avnumchop_on - double(2 * data_time_off) * avnumchop_off; double tdead_tot = tdead + double(grouplen) * tdeadint_on + tdeadint_off; // Add integration times of other frequencies as dead time tdead_tot = tdead_tot + double(grouplen - 1) * tdeadother; // Return total dead time and the dead times in the two chops return {tdead_tot,tphaseint_on,tphaseint_off,tswitch_on,tswitch_off}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure SScanFSwitchNoRef_commanding { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference characteristic LO frequency double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in both phases double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS tuning levels int data_time = 4; // chunk size int n_per_on = 1; // number of half load-sky-sky-load cycles on ON int n_load_on = 0; // additional load measurements in ON pointing phase int groupnumber = 4; // Total number of frequency groups int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,0]; // Timing of observation from telescope int loadlength = 50; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); bool retuneload = n_load_on > 0; // First frequency double runningfreq = freqgrid[grouporder[0][0]]; string[] targetnames = TargetNames(band,reffreq,retuning,targetlevels); string target = targetnames[0]; // All commands with a duration possibly depending on the frequency // are taken at the reference frequency to guarantee synchonization //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // HIFIInitObs(); TuneHIFIFsw(band,runningfreq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},target); delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { for(int i_freq = 0 .. groupnumber - 1) { // First frequency // Loop over load cycles for(int i1 = 1 .. n_load_on) { // Actual measurement HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFIFSwitchOnIntegration(data_time,n_per_on,band,reffreq,rates); // Perform load calibration delay(readoutdead); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms); } if(n_load_on == 0) { // This is the only measurement executed with nload=0 HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFIFSwitchOnIntegration(data_time,n_per_on,band,reffreq,rates); } // Other frequencies // Reset group counter for(int i_group = 1 .. grouplen - 1) { // retune runningfreq = freqgrid[grouporder[0][i_group] + i_freq * grouplen]; HIFIChangeFreqFsw(band,runningfreq,freq_throw); if(retuneload) { // First load SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms); } else { // This is the only measurement executed with nload=0 HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFIFSwitchOnIntegration(data_time,n_per_on,band,reffreq,rates); } // Loop over load cycles for(int i2 = 1 .. n_load_on) { // Actual measurement HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFIFSwitchOnIntegration(data_time,n_per_on,band,reffreq,rates); // Perform load calibration delay(readoutdead); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms); } } // Now we switch to the next frequency group or repeat the cycle // Big tuning step, but not at end of observation if(i_freq < groupnumber - 1) { runningfreq = freqgrid[grouporder[0][0] + (i_freq + 1) * grouplen]; target = targetnames[i_freq + 1]; HIFIRetuneFsw(band,runningfreq,freq_throw,target); // first load or main load for n_load=0 SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,retuneload,eff_resolution{0},data_time,backendreadoutparms); } } } if(state[0] == 5) { if(n_load_on == 0) { delay(readoutdead); } HIFICloseObs(); } } } ///////////////////////////////////////////////////////////////// // Procedure to derive the backend settings for spectral scans {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} procedure SScanBackendSettings { string band = "4a"; // HIFI band int redundancy = 4; // Frequency scan redundancy bool wbs1_used = true; // whether WBS1 is used bool wbs2_used = true; // whether WBS2 is used int data_time = 4; // data dump interval }{ // Standard configuration of the backends {bool,int[][]} wbs1 = {wbs1_used,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {wbs2_used,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS parameters ={used, channel windows} // Check whether we can use the HRS in parallel // Get fixed HRS parameters {{bool,int,double[],bool[]},{bool,int,double[],bool[]}} hrsparms = GetSpectralScanHRS(redundancy,band); {bool,int,double[],bool[]} hrs1 = hrsparms{0}; {bool,int,double[],bool[]} hrs2 = hrsparms{1}; string[] resolstring = ["high-resolution","nominal-resolution","low-resolution","wide-resolution"]; // Create a composite readout structure {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute chunk size given by the data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); // Test whether HRS can be used if(dataparms{0} > data_time) { // No HRS possible // HRS parameters when not used hrs1 = {false,1,[-110.0,110.0,0.0,0.0],[false,false,false,false]}; hrs2 = {false,1,[-110.0,110.0,0.0,0.0],[false,false,false,false]}; message("No parallel HRS usage due to short chop phase length.
"); // Create a composite readout structure backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); } else { message("HRS running parallel in " + resolstring[hrs1{1}] + " mode.
"); } return {hrs1,hrs2,wbs1,wbs2}; } {int,double,double,double,double,double} obs HifiPointModeFSwitchNoRef { string modeName = "fs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-FSwitch-NoReference",{data_time,0,0,0,0,0,0,0,n_cycles,load_interval}); // Two cases: fine pointing or position switch // Call first part of the timing computer {int,int,int,int,int,int,bool,int,int} pre_timing_f = FSwitchNoRef_pre_timing(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,pre_timing_f); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing_f = SingleChopNoRef_post_timing(pre_timing_f,telescopetimes); // Now the actual observation starts // Prepare telescope command tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,post_timing_f{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Consistency check int totaltime = post_timing_f{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// // standard parameters for fine pointing int loadlength = post_timing_f{1}{2}; int n_per_on = post_timing_f{1}{4}; int n_load_on = post_timing_f{1}{5}; bool end_load_on = post_timing_f{1}{6}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FSwitchNoRef_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on,n_load_on,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = FSwitchNoRef_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_per_on * (n_load_on + 1),tscan,tdead); // Evaluate performance SingleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_per_on * (n_load_on + 1),true,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ////////////////////////////////////////////////////////////////////// // Generic procedure to call a Configure_spectroscopy command // for total power and slow chop observations procedure ConfigureSpectroscopy { /* Integration time */ int data_time = 4; // Integration time between two data readouts int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string chopmode = "chop" in ["chop","lchop","fs","hot-cold","tp"]; // Chop mode determining the modulation dead time string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used,channel windows} }{ // Get timing parameters {int,int,int,int,int,int,int,int,int,int} timing = ConfigureSpectroscopyParams(data_time,n_data,chopmode,band,lo_freq,backendreadoutparms); int n_wbs_start = timing{0}; int r_hrs = timing{1}; int n_wbs_integr = timing{2}; int n_hrs_integr = timing{3}; int del_hrs = timing{4}; int del_wbs = timing{5}; int t_acc_wbs = timing{6}; int t_acc_hrs = timing{7}; // Transfer mode {int,int,int,int,int[],int[],string} backendconfigure = ConfigSpectroscopyBackends(data_time,backendreadoutparms); int wbs_rshift = backendconfigure{0}; int hrs_rshift = backendconfigure{1}; int hrsh_sel = backendconfigure{2}; int hrsv_sel = backendconfigure{3}; int[] wbsh_par = backendconfigure{4}; int[] wbsv_par = backendconfigure{5}; string packing = backendconfigure{6}; // Now call the command Hifi_HIFI_config_spectroscopy($BBID,n_wbs_start,r_hrs,n_wbs_integr,n_hrs_integr,del_hrs,del_wbs,t_acc_wbs,t_acc_hrs,wbsh_par[0],wbsh_par[1],wbsh_par[2],wbsh_par[3],wbsh_par[4],wbsh_par[5],wbsh_par[6],wbsh_par[7],wbsv_par[0],wbsv_par[1],wbsv_par[2],wbsv_par[3],wbsv_par[4],wbsv_par[5],wbsv_par[6],wbsv_par[7],hrs_rshift,wbs_rshift,hrsh_sel,hrsv_sel,packing); // // No delay for a configuration command } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for a // Spectral Scan Frequency-Switch observing mode // {{int,int,int,int,int,int,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} procedure SScanFSwitchNoRef_pre_timing { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_chop_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Create composite readout structure for backends {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get frequency grid characteristic parameters {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq_low,lo_freq_up,redundancy,freq_throw,n_freq_point); int groupnumber = fqparms{0}; double reffreq = fqparms{1}; double[] freqgrid = fqparms{2}; int[][] grouporder = fqparms{3}; // Process tuning level grid double[][] levelgrid = GetSScanLevelGrid(band,wbs1,wbs2,freqgrid,fqparms{0},grouporder); {bool,double[]} targets = TargetLevels(band,reffreq,levelgrid); bool retuning = targets{0}; double[] targetgrid = targets{1}; string reftarget = ""; if(retuning) { reftarget = "sscan_normal"; } {int,double,double[],int[][],bool,double[],int,bool} spectralparms = {fqparms{0},reffreq,freqgrid,grouporder,retuning,targetgrid,fqparms{4},fqparms{5}}; ////////////////////////////////////////////////////////////////////// // Get timing within the normal frequency-switch observations int jitterdead = GetMaxTimeJitter(band,reffreq); // Integration time per frequency and pointing int on_inttime = 2 * n_chop_on * data_time; // Tuning delays int bigtunestep = duration(HIFIRetuneFsw(band,reffreq,freq_throw,reftarget)); // Correct for variation within the band int tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq); bigtunestep = bigtunestep + 2 * tunediff; // A step within a group could be faster than a large step if(n_freq_point > 1) { int smallstep = duration(HIFIChangeFreqFsw(band,reffreq,freq_throw)); } else { smallstep = bigtunestep; } int grouptime = n_freq_point * on_inttime + (n_freq_point - 1) * smallstep; // Compute load integration time int loadlength = duration(SScanDoubleLoadMeasurement(band,reffreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); loadlength = loadlength + readoutdead; // Duration of initial set up // Staying at the same frequency makes no sense here. // First frequency point double runningfreq = freqgrid[grouporder[0][0]]; // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFIFsw(band,runningfreq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,runningfreq,true); } initlength = initlength + loadlength; int initloadlength = loadlength; // Compare load interval with duration of the observation int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); if(load_spacing < grouptime && n_freq_point > 1) { SError("Load period too short for frequency group size."); } // Here we bracket each cycle by loads, this leads to a grace period int n_load_on = on_inttime / load_spacing; // In the following the definition of n_load_on is higher by 1 relative to // that used in normal frequency switch! // This determines the order of the loops if(n_load_on == 0) { int n_per_on = n_chop_on; bool end_load_on = false; // recompute load length in case of short integrations loadlength = duration(SScanDoubleLoadMeasurement(band,reffreq,reffreq,freq_throw,false,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; } else { // grace condition if(double(on_inttime) > 1.2 * double(load_spacing)) { n_load_on = n_load_on + 1; } n_per_on = n_chop_on / n_load_on; if(n_per_on < 1) { SError("FS phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * n_load_on * data_time; // This cannot happen for n_freq_point > 1 grouptime = on_inttime + n_load_on * loadlength; } int on_pointing = groupnumber * (grouptime + bigtunestep + loadlength) - bigtunestep - loadlength + jitterdead; // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {{on_inttime,on_pointing,initloadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling},spectralparms}; } // Interpolate differential total power load chop Allan time and exponent double[] procedure InterpolateTpLChopAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ // subband is not used yet double[] allan = CalibrationReader("loadchop_Allan",["tp_Allan_time","tp_Allan_exp","tp_binning_exp"],band,lo_freq); return allan; } {string,double,double}[] procedure HifiPointModeLoadChopSequencerInit { string modeName = "load"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half load-sky-sky-load cycles on ON int n_switch_off = 2 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = LoadChopPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_guess = imax(iceil(phaselengths{0} / (2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; new_data_time = MatchMinPointing(data_time_off_guess,data_time_off_range,2 * n_switch_off_guess); data_time_off_guess = new_data_time{0}; data_time_off_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)}]; return retvalues; } // Procedure to get timing in a spectroscopy measurement {double,double} procedure GetInstDeadSlowChop { /* Integration time */ int data_time = 4; // Integration time between two data readouts int n_int = 2; // Integration time counter string chopmode = "chop" in ["chop","lchop","fs","hot-cold","tp"]; // Chop mode determining the modulation dead time /* Parameters determining the delays - used in calibration reader */ string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used,channel windows} }{ // Get timing parameters {int,int,int,int,int,int,int,int,int,int} timing = ConfigureSpectroscopyParams(data_time,n_int,chopmode,band,lo_freq,backendreadoutparms); int tdead = timing{8}; int tint = timing{9}; // Return dead time per full integration double tintall = double(tint) / 1000.0; double tdeadphase = double(tdead) / 1000.0; return {tintall,tdeadphase}; } // Combine radiometric and drift noise from an OTF observation // Normalized to mapping without overhead // {double,double} procedure OtfNoiseValues { double n = 10.0; // number of points in one scan double[] parameters = [0.02,0.4,0.05,0.667,2.5]; // Parameters: integration time, delay, slew from OFF relative to Allan time, ratio of t_off time to sqrt(n)*t_on, drift exponent }{ // Assign parameters double npoints = double(ifloor(n)); double x = parameters[0]; double d = parameters[1]; double doff = parameters[2]; double qval = parameters[3]; double alpha = parameters[4]; if(npoints > 0.0) { // OFF integration time double xr = qval * sqrt(npoints) * x; // Total delay double dtot = (npoints - 1.0) * x + d; // Try two points at the edge and the center of a scan to get the extremes double[] pp = [0.0,0.5]; double[] yn = [0.0,0.5]; double[] yd = [0.0,0.5]; double[] yy = [0.0,0.5]; double p = 0.0; for(int ip = 0 .. 1) { p = pp[ip]; // Delay length before measured point double d1 = doff + double(ifloor(p * npoints)) * x + p * (d - 2.0 * doff); // Remaining delay double d2 = dtot - d1; // add radiometric and drift noise yn[ip] = OtfRadioNoise(x,xr,d1,d2); yd[ip] = OtfDrift(x,xr,d1,d2,alpha); yy[ip] = yn[ip] + yd[ip]; } // Normalization - relative to mapping without overhead double norm = (x + xr + dtot) / npoints; // Get worst case if(yy[0] > yy[1]) { double ynm = yn[0] * norm; double ydm = yd[0] * norm; } else { ynm = yn[1] * norm; ydm = yd[1] * norm; } // Artificially forbid OTF scans much longer than the Allan time double driftadd = max(dtot + x - 10.0,0.0) * 0.1; ydm = ydm + driftadd * ynm; } else { // forbid negative point numbers ynm = 1.0E11; ydm = 1.0E11; } return {ynm,ydm}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure SScanLoadChopNoRef_commanding { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference characteristic LO frequency {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in both phases double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS tuning levels int data_time = 4; // chunk size int n_per_on = 1; // number of half load-sky-sky-load cycles on ON int n_load_on = 0; // additional load measurements in ON pointing phase int groupnumber = 4; // Total number of frequency groups int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,0]; // Timing of observation from telescope int loadlength = 50; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); bool retuneload = n_load_on > 0; // First frequency double runningfreq = freqgrid[grouporder[0][0]]; string[] targetnames = TargetNames(band,reffreq,retuning,targetlevels); string target = targetnames[0]; // All commands with a duration possibly depending on the frequency // are taken at the reference frequency to guarantee synchonization //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // HIFIInitObs(); TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},target); delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { for(int i_freq = 0 .. groupnumber - 1) { // First frequency // Loop over load cycles for(int i1 = 1 .. n_load_on) { // Actual measurement HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFILoadChopOnIntegration(data_time,n_per_on,band,reffreq,rates); // Perform load calibration delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms); } if(n_load_on == 0) { // This is the only measurement executed with nload=0 HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFILoadChopOnIntegration(data_time,n_per_on,band,reffreq,rates); } // Other frequencies // Reset group counter for(int i_group = 1 .. grouplen - 1) { // retune runningfreq = freqgrid[grouporder[0][i_group] + i_freq * grouplen]; HIFIChangeFreq(band,runningfreq); if(retuneload) { // First load SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms); } else { // This is the only measurement executed with nload=0 HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFILoadChopOnIntegration(data_time,n_per_on,band,reffreq,rates); } // Loop over load cycles for(int i2 = 1 .. n_load_on) { // Actual measurement HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); HIFILoadChopOnIntegration(data_time,n_per_on,band,reffreq,rates); // Perform load calibration delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms); } } // Now we switch to the next frequency group or repeat the cycle // Big tuning step, but not at end of observation if(i_freq < groupnumber - 1) { runningfreq = freqgrid[grouporder[0][0] + (i_freq + 1) * grouplen]; target = targetnames[i_freq + 1]; HIFIRetuneFreq(band,runningfreq,target); // first load or main load for n_load=0 SScanLoadMeasurement(band,runningfreq,reffreq,retuneload,eff_resolution{0},data_time,backendreadoutparms); } } } if(state[0] == 5) { if(n_load_on == 0) { delay(readoutdead); } HIFICloseObs(); } } } // Total noise from an asymmetric double difference observation // This is still to be scaled by a factor 1.0/(B_fluct*T_obs) double procedure DoubleDifferenceNoise { double x = 0.1; // value for integration time relative to Allan time double[] parameters = [1.0,1.0,0.8,0.8,0.05,0.3,2.5,5.0,2.5]; // Parameters: ratio of integration times, ratio of effective resolutions, delay in phase1, in phase 2, between phases relative to Allan time, drift exponents }{ // Assign parameters double tpa = parameters[2]; // total length of A pointing phase double tpb = parameters[3]; // total length of B pointing phase double d = parameters[5]; // position switch dead time relative to differential Allan {double,double} noisevalues = DoubleDifferenceNoiseValues(x,parameters); // Add and normalize with respect to total observing time double y = (noisevalues{0} + noisevalues{1}) * (tpa + tpb + d); return y; } // Perform load chop integration at OFF position ON-OFF-OFF-ON... block HIFILoadChopOffIntegration HIFI 6036 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_cold","chop_M3"],rates); } // Noise ratio from an asymmetric double difference observation double procedure DoubleDifferenceNoiseRatio { double x = 0.1; // value for integration time relative to Allan time double[] parameters = [1.0,1.0,0.8,0.8,0.05,0.3,2.5,5.0,2.5]; // Parameters: ratio of integration times, ratio of effective resolutions, delay in phase1, in phase 2, between phases relative to Allan time, drift exponents }{ {double,double} noisevalues = DoubleDifferenceNoiseValues(x,parameters); double y = noisevalues{1} / noisevalues{0}; return y; } // Give sequence of frequency steps in a spectral scan mode within one group double[][] procedure SpreadHRS { string band = "4a"; // HIFI band int[] resolution = [1,1]; // Frequency resolution double[] offset = [0.0,0.0]; // Center offsets }{ // Define using the values for resolution=0 double[][] settings = [[offset[0],0.0,0.0,0.0],[offset[1],0.0,0.0,0.0]]; // set up individually for the two HRS's for(int i = 0 .. 1) { int res = resolution[i]; double off = offset[i]; // create settings if(res == 0) { double[] subset = [off,0.0,0.0,0.0]; } else { // Set subband width double singlewidth = GetBackendBandwidth(band,0.0,res); // Arrange with some overlap double hrsgranularity = 20.0; double doff = 0.5 * (singlewidth - hrsgranularity); if(res == 1) { subset = [off - doff,off + doff,0.0,0.0]; } else { subset = [off - 3.0 * doff,off - doff,off + doff,off + 3.0 * doff]; } } settings[i] = subset; } return settings; } //////////////////////////////////// // OTF frequency switch observing mode // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcFSwitchOTF { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-FSwitch-OTF",{data_time,data_time_off,0,n_switch_on,n_switch_off,n_linesperscan,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,int,int,int,int} pre_timing = OTFFSwitch_pre_timing(nlines,npoints_used,band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_with_off_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int},double,double} post_timing = OTFmap_post_timing(pre_timing,telescopetimes,data_time,n_linesperscan,n_cycles,load_interval); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_with_off_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int n_pp = post_timing{1}{0}; int n_scans = post_timing{1}{1}; int off_inttime = post_timing{1}{2}; int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{5}; double tscan = post_timing{2}; double tdead = post_timing{3}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFFSwitch_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,npoints_used * n_switch_on,n_switch_off,nlines * n_cycles,n_linesperscan,n_loadinterval,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double,double,double} tact = OTFDoubleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,n_pp,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = OTFFSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,nlines,data_time,n_switch_on,n_linesperscan,off_inttime,n_cycles,tscan,tact); // Evaluate performance OTFDoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on,n_switch_off,n_scans,n_cycles,true,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Change of HK rate - setting of corresponding data rates block HIFISetHK HIFI 6001 { string speed = "normal" in ["fast","normal","slow"]; // Select HK rate bool active = false; // Whether to actively query the spectrometers }{ // Get parameters {string,int,double,double,double,double} hkparms = PeriodicHKParms(speed); non_ess_hk_data_rate(hkparms{3} / 1024.0); ess_hk_data_rate(hkparms{5} / 1024.0); // Subsystems to be queried string[] pattern = QueryHKPattern(active); Hifi_HIFI_Housekeeping_on(hkparms{0},pattern[0],pattern[1],pattern[2],pattern[3],pattern[4],pattern[5]); delay(1); } // Add two vectors defined as tuples {double,double} procedure AddVectors { {double,double} vector1 = {1.0,1.0}; {double,double} vector2 = {1.0,1.0}; }{ return {vector1{0} + vector2{0},vector1{1} + vector2{1}}; } {string,double,double}[] procedure HifiMappingModeFSwitchOTFNoRefSequencerInit { string modeName = "fs-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // inherit from load-chop mode {string,double,double}[] retvalues = HifiMappingProcLoadChopOTFNoRefSequencerInit(naifid,ra,dec,lineDistance,nlines,stepsize,npoints,band,lo_freq,effResolution,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); return retvalues; } {string,double,double}[] procedure HifiMappingModeFastDBSCrossSequencerInit { string modeName = "cross"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // inherit from dbs-raster mode {string,double,double}[] retvalues = HifiMappingProcFastDBSRasterSequencerInit(naifid,ra,dec,{0.0,double(npoints / 2) * stepsize},2,stepsize,npoints,band,lo_freq,effResolution,continuumDetection,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); return retvalues; } //Compute "real" frequencies double procedure Compute_Real_Freq { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency }{ //Read parameters double[] result = CalibrationReader("name_lsu_convertion",["multiplier","f_offset","n10","n20"],band,lo_freq); double multiplier = result[0]; double f_offset = result[1]; int n10 = iround(result[2]); int n20 = iround(result[3]); // //Compute LSU frequency IN MHZ double f_lsu = lo_freq * 1000.0 / multiplier; //Compute total frequency double f_total = f_lsu + f_offset; //Compute parameter n int n = ifloor(15.0 * (f_total / 1.875 - double(ifloor(f_total / 1.875)))); //Compute main and offset loop parameters int n1 = n10 + n; // offset loop int d1 = 15; //offset loop int n2 = iround(abs(double(n20 - ifloor(f_total / 1.875) + n))); //main loop int d2 = 16; // //Compute A,M and R parameters for main and offset loop int m1 = ifloor(double(n1) / 10.0) - 1; // offset loop int a1 = n1 - 10 * ifloor(double(n1) / 10.0); // offset loop int r1 = d1 - 1; // offset loop int m2 = ifloor(double(n2) / 10.0) - 1; // main loop int a2 = n2 - 10 * ifloor(double(n2) / 10.0); // main loop int r2 = d2 - 1; // main loop // int[] lsu_a_m_r_parameter = [0,0,0,0,0,0]; lsu_a_m_r_parameter[0] = m1; lsu_a_m_r_parameter[1] = a1; lsu_a_m_r_parameter[2] = r1; lsu_a_m_r_parameter[3] = m2; lsu_a_m_r_parameter[4] = a2; lsu_a_m_r_parameter[5] = r2; // //Conversion into main and offset LSU word int main_word = iround(pow(2.0,18.0) * double(ifloor(double(r2) % pow(2.0,6.0) / pow(2.0,4.0))) + pow(2.0,15.0) * double(ifloor(double(m2) % pow(2.0,9.0) / pow(2.0,7.0))) + pow(2.0,8.0) * (double(m2) % pow(2.0,9.0)) + pow(2.0,4.0) * (double(r2) % pow(2.0,6.0) % pow(2.0,4.0)) + double(a2) % pow(2.0,4.0)); int offset_word = iround(pow(2.0,18.0) * double(ifloor(double(r1) % pow(2.0,6.0) / pow(2.0,4.0))) + pow(2.0,15.0) * double(ifloor(double(m1) % pow(2.0,9.0) / pow(2.0,7.0))) + pow(2.0,8.0) * (double(m1) % pow(2.0,9.0)) + pow(2.0,4.0) * (double(r1) % pow(2.0,6.0) % pow(2.0,4.0)) + double(a1) % pow(2.0,4.0)); // //debug_print("LSU conversion result " + lsu_a_m_r_parameter); //debug_print("main: " + main_word + ", offset: " + offset_word); // //Compute real LO frequency set by A,M,R combination double nn1 = double(10 * (m1 + 1) + a1); double dd1 = double(r1 + 1); double nn2 = double(10 * (m2 + 1) + a2); double dd2 = double(r2 + 1); double flsu_back = 24000.0 + 30.0 * (nn1 / dd1 + nn2 / dd2); if(band == "2a" || band == "3b") { flsu_back = 24000.0 + 30.0 * (nn1 / dd1 - nn2 / dd2); } double flo_back = flsu_back * multiplier; //debug_print("Real tuned frequency: " + flo_back); // return flo_back; } {string,double,double}[] procedure HifiPointModeFastDBSSequencerInit { string modeName = "dbs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities // Top down approach here int main_phase = iceil(phaselengths{0}); int data_time_guess = 40; int n_switch_on_guess = main_phase / data_time_guess; if(n_switch_on_guess < 2) { n_switch_on_guess = 2; data_time_guess = main_phase / n_switch_on_guess; } // Check with data rate {int,double[]} dataparms = DataTaking(backendreadoutparms,8); int datalimit = 2 * dataparms{0}; if(data_time_guess < datalimit) { data_time_guess = datalimit; n_switch_on_guess = 1; } int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Chop phase length double phase_min = min(max(phaselengths{1},0.15),1.5); int n_int_on_guess = ifloor(double(data_time_guess) / (2.0 * phase_min)); int n_int_on_range = -n_int_on_guess / 2; if(n_int_on_range == 0) { n_int_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)}]; return retvalues; } ////////////////////////////////////////////////////////// // New building blocks // Slow chop integration at source position OFF-ON-ON-OFF... block HIFIHalfChopOnIntegration HIFI 6051 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3","chop_M3right"],rates); } {int,double,double,double,double,double} obs HifiPointModeLoadChop { string modeName = "load"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half load-sky-sky-load cycles on ON int n_switch_off = 2 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-LoadChop",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,0,n_cycles,load_interval}); // position switch // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing_ps = LoadChop_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,pre_timing_ps,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},int,bool,double,double} post_timing_ps = DoubleChop_post_timing(pre_timing_ps,telescopetimes,n_cycles); // Now the actual observation starts // Prepare telescope command tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,post_timing_ps{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Consistency check int totaltime = post_timing_ps{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// int on_inttime = post_timing_ps{1}{0}; int off_inttime = post_timing_ps{1}{1}; int on_pointing = post_timing_ps{1}{2}; int off_pointing = post_timing_ps{1}{3}; int loadlength = post_timing_ps{1}{4}; int n_loadinterval = post_timing_ps{1}{7}; int n_per_on = post_timing_ps{1}{8}; int n_per_off = post_timing_ps{1}{9}; int n_load_on = post_timing_ps{1}{10}; int n_load_off = post_timing_ps{1}{11}; bool end_load_on = post_timing_ps{1}{12}; bool end_load_off = post_timing_ps{1}{13}; int initshiftlength = post_timing_ps{2}; bool final_load = post_timing_ps{3}; double tscan = post_timing_ps{4}; double tdead = post_timing_ps{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { LoadChop_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_loadinterval,n_load_on,n_load_off,end_load_on,end_load_off,final_load,startobs,telescopetimes,loadlength,initshiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = DoubleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_load_on,n_load_off,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = LoadChop_noisecomputer(band,lo_freq,effResolution,oneGHzReference,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance DoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_per_on * (n_load_on + 1),n_per_off * (n_load_off + 1),false,tscan,on_pointing,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Change the LO frequency to a new setting, keep backend settings procedure HIFITuneFreq { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; //LO frequency bool newsetting = true; // whether LSU/LOU parameters are new string target_name = "sscan_normal"; // Name of target level }{ // //LO power tuning: could use either H or V polar {double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq); double x = result[0]{0}; string tuningbackend = "H"; if(iround(x) == 2) { tuningbackend = "V"; } else { tuningbackend = "H"; } //LO frequency tuning, and store in FSW register LO_tuning_block_aot(band,lo_freq / 1000.0,lo_freq / 1000.0,tuningbackend,newsetting,newsetting,false); //Spectrometer attenuator tuning - on the sky or cold load if(target_name != "") { WBS_attenuators_block(band,lo_freq / 1000.0,target_name,true); } } // Total noise from an OTF observation // double procedure OtfNoise { double n = 10.0; // number of points in one scan double[] parameters = [0.02,0.4,0.05,0.667,2.5]; // Parameters: integration time, delay, slew from OFF relative to Allan time, ratio of t_off time to sqrt(n)*t_on, drift exponent }{ {double,double} noisevalues = OtfNoiseValues(n,parameters); double y = noisevalues{0} + noisevalues{1}; return y; } int block HIFI_Calibrate_hot_cold HIFI 6005 { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency int data_time = 4; // time between subsequent data readouts int n_data = 2; // Integration time counter {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 bool staycal = false; // whether we should stay at the hot load at the end }{ // data rate and read-out time {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int readout = dataparms{0}; // send the configure spectroscopy command to configure the measurement // returned dead times not needed here ConfigureSpectroscopy(data_time,n_data,"hot-cold",band,lo_freq,backendreadoutparms); HIFI_Spectr_slow_chop_proc_aot(data_time,n_data / 2,band,lo_freq,["chop_hot","chop_cold"],dataparms{1}); if(!staycal) { // Emit NOOP command to have the chopper rotation in second bus slot Hifi_HIFI_noop(); // Move chopper back to the sky RotateChopper(band,lo_freq,"chop_M3"); } // delay required at the end int sdelay = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // have clean bus timing for next spectroscopy block delay(sdelay); return readout; } // get backend bandwidth coverage (HRS only) double procedure GetBackendBandwidth { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency int res_mode = 0; // coding for the backend resolution mode }{ if(res_mode < 0 || res_mode > 3) { double[] resol = CalibrationReader("backendresolution",["wbs_bandwidth"],band,lo_freq); } if(res_mode == 0) { resol = CalibrationReader("backendresolution",["hrs_high_bandwidth"],band,lo_freq); } if(res_mode == 1) { resol = CalibrationReader("backendresolution",["hrs_normal_bandwidth"],band,lo_freq); } if(res_mode == 2) { resol = CalibrationReader("backendresolution",["hrs_low_bandwidth"],band,lo_freq); } if(res_mode == 3) { resol = CalibrationReader("backendresolution",["hrs_wide_bandwidth"],band,lo_freq); } return resol[0]; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the peakup mode procedure Peakup_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_int = 1; // number of readouts double eff_resolution = 1.0; // Minimum goal resolution in MHz double stepsize = 0.0050; // Distance between subsequent points in the raster line int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,10,29,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration }{ // Auxiliary variables bool isWbs = wbs1{0} || wbs2{0}; // Whether to use WBS bool isH = wbs1{0} || hrs1{0}; // Whether to use H polarization // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Different numbering in telescope command and peakup // Numbering starts from -Z,-Y, and proceeds first towards +Z int[] pointtable = [1,2,3,6,5,4,7,8,9]; // Get all values from the telescope section int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); HIFISetHK("normal",false); // First load measurement LoadMeasurement(band,lo_freq,eff_resolution,data_time,backendreadoutparms); HifiPeakupConfigure(data_time,n_int,isH,band,lo_freq,stepsize,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { int pointnumber = pointtable[state[2] - 1]; // In raster - actual measurement HIFIPeakupIntegration(data_time,n_int,isWbs,isH,pointnumber,band,lo_freq,rates); } // Final state if(state[0] == 5) { delay(readoutdead); // Perform AOCS correction HifiPeakupCorrection(); HIFICloseObs(); } } } // Get load temperatures {double,double} procedure LoadTemperatures { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ // Get temperatures double[] temp = CalibrationReader("loadtemp",["hot_temperature","cold_temperature"],band,lo_freq); double t_hot = temp[0]; double t_cold = temp[1]; // Get coupling specific for each band temp = CalibrationReader("loadcoupling",["hot_coupling","cold_coupling"],band,lo_freq); double c_hot = temp[0]; double c_cold = temp[1]; // Translate into radiation temperatures double hoverk = 4.7992E-5; double j_hot = hoverk * lo_freq / (exp(hoverk * lo_freq / t_hot) - 1.0); double j_cold = hoverk * lo_freq / (exp(hoverk * lo_freq / t_cold) - 1.0); // Coupling double j_hot_eff = j_hot * c_hot + j_cold * (1.0 - c_hot); double j_cold_eff = j_cold * c_cold + j_hot * (1.0 - c_cold); return {j_hot_eff,j_cold_eff}; } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure SScanFSwitch_noisecomputer { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference LO frequency in scan center int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz int on_inttime = 16; // Integration time per ON phase int off_inttime = 16; // Integration time per OFF phase int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ // spectral scans always use the full bandwidth for reference bool oneGHzReference = false; // Call FS noise computer {double,double,double,double,double} noisevalues = FSwitch_noisecomputer(band,reffreq,eff_resolution,oneGHzReference,on_inttime,off_inttime,n_cycles,tscan,tact); // Correct for multiple frequencies double multiplier = sqrt(1.0 / double(nfreq)); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; // Check for double sideband coverage if(dsb) { // Combine LSB-USB noise // In spectral scans we have only a combined noise temperature for both // sidebands, so that the USB/LSB separation is not used double[] gssb = InterpolateGssb(band,reffreq); double usbnoise_lores = noisevalues{0} / sqrt(1.0 + gssb[1] / gssb[0] * (gssb[1] / gssb[0])); double usbnoise_hires = noisevalues{1} / sqrt(1.0 + gssb[1] / gssb[0] * (gssb[1] / gssb[0])); double lsbnoise_lores = usbnoise_lores; double lsbnoise_hires = usbnoise_hires; } else { // Get single sideband noise equivalent usbnoise_lores = noisevalues{0}; usbnoise_hires = noisevalues{1}; lsbnoise_lores = noisevalues{2}; lsbnoise_hires = noisevalues{3}; } // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noisevalues{4}}; } // Length of a vector in degrees double procedure VectorLength { {double,double} vector = {1.0,1.0}; }{ return sqrt(vector{0} * vector{0} + vector{1} * vector{1}); } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the DBS raster mode procedure FastDBSRaster_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_seq = 1; // number of data transfer cycles per pointing int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles int n_pointsperscan = 1; // Number of points measured before moving to the second pointing phase int n_loadinterval = 10; // number of nods before a load measurement int n_load = 0; // additional load measurements in one pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,0,10,20,21,0,0,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration bool iscross = false; // Whether we use a cross instead of a raster }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int load_datatime = GetStdLoadReadout(band,lo_freq); // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time / 2); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); // There is no nod counter in the return values - count this by hand int inod = 0; // Do I have to make loads in short nods and subsequent holds? if(iscross) { bool holdforload = n_pointsperscan > 1; } else { holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles; } //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; int[] choppars = [2 * n_int,0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - hkduration - loadlength); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles // The use of n_load differs by 1 from the other observing modes here for(int i1 = 1 .. n_load - 1) { HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: // n_pointsperscan=1, n_loadinterval > n_cycles if(state[3] % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } } // Second pointing phase if(state[0] == 7) { // second nod position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); for(int i2 = 1 .. n_load - 1) { HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: if(state[3] % 2 == 0) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } } // Load nod if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } // Hold if(state[0] == 6) { // finished shift of instrument operations relative to pointing command runintostate = false; } // Final load if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the OTF observing mode procedure OTFLoadChopNoRef_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int n_perline = 10; // Number of frequency switch cycles per line int n_linesperscan = 1; // Number of lines between two load holds int nlines_tot = 10; // Total number of lines to go bool end_load_on = false; // Need for load after each pointing phase int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,2,2,40,10,20,0]; // Timing of the observation from telescope int loadlength = 50; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); HIFISetHK("normal",false); // First load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 8) { // OTF integration // Check whether this is the first line if((state[2] + n_linesperscan - 1) % n_linesperscan == 0) { HIFIConfigureLoadChopIntegration(data_time,n_perline,band,lo_freq,backendreadoutparms); } HIFILoadChopOnIntegration(data_time,n_perline,band,lo_freq,rates); runintostate = false; } if(state[0] == 6) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); if(state[2] * state[3] == nlines_tot) { runintostate = true; } else { runintostate = false; } } if(state[0] == 5) { // apply only if I do not come from a load-hold if(!runintostate) { delay(readoutdead); if(end_load_on) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } } runintostate = false; HIFICloseObs(); } } } // Initialisation of FPU, block with both MSA in use // It is for cold context ! block Init_MSA_aot HIFI 6200 { string band = "4a"; // HIFI band string chop_loop = "CLOSE"; double lo_freq = 978.2; //LO frequency bool power_fcu = true; //whether needs full FPU configuration (true) or just freq-dependent adjustement (false) string hbb_heater = "ON" in ["ON","OFF"]; //hot source on/off }{ //Store rest frequency double rest_lofreq = lo_freq; //LO frequency uncorrected from VelCorr // Perform radial velocity correction lo_freq = VelCorrFreq(rest_lofreq); //Get parameters {double,string}[] result_d = ConfigurationReader("name_confilfpu",["band","fif1v_h","fif1c_h","fif2v_h","fif2c_h","sif1v_h","sif1c_h","sif2v_h","sif2c_h","sif3v_h","sif3c_h"],band,lo_freq); int band_nb = iround(result_d[0]{0}); double diplex_H = 0.0; double diplex_V = 0.0; int diplex_h_ctrl_mode = 0; int diplex_v_ctrl_mode = 0; // double volt_H_FIF_1 = result_d[1]{0}; double curr_H_FIF_1 = result_d[2]{0}; double volt_H_FIF_2 = result_d[3]{0}; double curr_H_FIF_2 = result_d[4]{0}; // double volt_H_SIF_1 = result_d[5]{0}; double curr_H_SIF_1 = result_d[6]{0}; double volt_H_SIF_2 = result_d[7]{0}; double curr_H_SIF_2 = result_d[8]{0}; double volt_H_SIF_3 = result_d[9]{0}; double curr_H_SIF_3 = result_d[10]{0}; // result_d = ConfigurationReader("name_confilfpu",["fif1v_v","fif1c_v","fif2v_v","fif2c_v","sif1v_v","sif1c_v","sif2v_v","sif2c_v","sif3v_v","sif3c_v"],band,lo_freq); // double volt_V_FIF_1 = result_d[0]{0}; double curr_V_FIF_1 = result_d[1]{0}; double volt_V_FIF_2 = result_d[2]{0}; double curr_V_FIF_2 = result_d[3]{0}; // double volt_V_SIF_1 = result_d[4]{0}; double curr_V_SIF_1 = result_d[5]{0}; double volt_V_SIF_2 = result_d[6]{0}; double curr_V_SIF_2 = result_d[7]{0}; double volt_V_SIF_3 = result_d[8]{0}; double curr_V_SIF_3 = result_d[9]{0}; // string chop_sine_s = "ON"; // string chop_loop = "CLOSE" ; result_d = ConfigurationReader("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2","chop_g3","chop_p3","calibrator_current"],band,lo_freq); // int chop_G1 = iround(result_d[0]{0}); int chop_G2 = iround(result_d[1]{0}); int chop_Z1 = iround(result_d[2]{0}); int chop_Z2 = iround(result_d[3]{0}); int chop_P2 = iround(result_d[4]{0}); // double calibcurrent = result_d[7]{0}; if(hbb_heater == "ON") { result_d = ConfigurationReader("name_confilfpu",["calibrator_current_on"],band,lo_freq); calibcurrent = result_d[0]{0}; } // // //Get biases result_d = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq); double bias_H = result_d[0]{0}; double bias_V = result_d[1]{0}; //For bands 6 and 7, first set to 4mV if(band == "6a" || band == "6b" || band == "7a" || band == "7b") { result_d = ConfigurationReader("name_confilfpu",["bias_max_h","bias_max_v"],band,lo_freq); bias_H = result_d[0]{0}; bias_V = result_d[1]{0}; } // //Get magnets: not applicable to bands 6 and 7 double magnetcurrent_H = 0.0; double magnetcurrent_V = 0.0; if(band != "6a" && band != "6b" && band != "7a" && band != "7b") { result_d = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,lo_freq); magnetcurrent_H = result_d[0]{0}; magnetcurrent_V = result_d[1]{0}; } //Diplexer is interpolated from a table for Bands 3, 4, 6L and 6H if(band_nb <= 2 || band_nb == 5) { diplex_H = 0.0; //For bands 1, 2 and 5 diplex_V = 0.0; diplex_h_ctrl_mode = 0; diplex_v_ctrl_mode = 0; } else { //Get diplexer currents result_d = ConfigurationReader("name_confilfpu",["diplex_h_ctrl_mode","diplex_v_ctrl_mode"],band,lo_freq); diplex_h_ctrl_mode = iround(result_d[0]{0}); diplex_v_ctrl_mode = iround(result_d[1]{0}); double[] result_dip = Get_Diplexer_setting(band,lo_freq); diplex_H = result_dip[0]; diplex_V = result_dip[1]; } // result_d = ConfigurationReader("name_chopper",["chop_startup_cold"],band,lo_freq); if(chop_loop == "OPEN") { result_d = ConfigurationReader("name_chopper",["chop_startup_warm"],band,0.0); } double chopper = result_d[0]{0}; //For this configuration we won't convert prime chopper voltage into redundant voltage //Just checking we are in range: not necessary anymore with MIB134 //chopper = Check_Chopper_Range(chopper); // //Check whether we need to go through a complete FPU configuration from scratch //Standard Init of FPU if(power_fcu) { //Switch on upconverter, assuming chopper and mixers are also ON Hifi_HIFI_Configure_FCU_Power($BBID,"ON","ON","ON","ON","ON"); // HIFI_Configure_FCU_proc_aot(band_nb,diplex_h_ctrl_mode,volt_H_FIF_1,curr_H_FIF_1,volt_H_FIF_2,curr_H_FIF_2,volt_H_SIF_1,curr_H_SIF_1,volt_H_SIF_2,curr_H_SIF_2,volt_H_SIF_3,curr_H_SIF_3,diplex_v_ctrl_mode,volt_V_FIF_1,curr_V_FIF_1,volt_V_FIF_2,curr_V_FIF_2,volt_V_SIF_1,curr_V_SIF_1,volt_V_SIF_2,curr_V_SIF_2,volt_V_SIF_3,curr_V_SIF_3,chop_sine_s,chop_loop,chop_G1,chop_G2,chop_Z1,chop_Z2,chop_P2,calibcurrent,bias_H,magnetcurrent_H,bias_V,magnetcurrent_V,chopper,diplex_H,diplex_V); // result_d = ConfigurationReader("name_delays",["config_fpu_delay"],band,rest_lofreq); int config_fpu_delay = iround(result_d[0]{0}); delay(config_fpu_delay); // //Magnet are so far at maximum value. Now set to nominal if(band != "6a" && band != "6b" && band != "7a" && band != "7b") { result_d = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v"],band,lo_freq); Hifi_HIFI_CH1_MX_MG_C($BBID,result_d[0]{0}); Hifi_HIFI_CV1_MX_MG_C($BBID,result_d[1]{0}); delay(1); } //In case of band 6 or 7, bias have been set to 6mV. Now set to nominal if(band == "6a" || band == "6b" || band == "7a" || band == "7b") { result_d = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq); Mixerbias(result_d[0]{0},result_d[1]{0}); } //Reduced FPU configuration } else { //In case of HEB, we have so far the max bias as values if(band == "6a" || band == "6b" || band == "7a" || band == "7b") { result_d = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq); bias_H = result_d[0]{0}; bias_V = result_d[1]{0}; } Hifi_HIFI_noop(); Hifi_HIFI_Config_mxbias_dpact($BBID,bias_H,bias_V,diplex_H,diplex_V); delay(1); } // // Removed to reduce No of TC // Hifi_HIFI_non_periodic_hk_FCU (); } //////////////////////////////////// // OTF frequency switch observing mode without baseline calibration // {string,double,double}[] procedure HifiMappingProcFSwitchOTFNoRefSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // inherit from load-chop mode {string,double,double}[] retvalues = HifiMappingProcLoadChopOTFNoRefSequencerInit(naifid,ra,dec,lineDistance,nlines,stepsize,npoints,band,lo_freq,effResolution,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); return retvalues; } // Get approximate initialization times int procedure GetRoughInitLength { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool fsw = false; // tuning for frequency switch? }{ if(fsw) { double[] idur = CalibrationReader("tunetime",["TuneHifiFsw"],band,lo_freq); } else { idur = CalibrationReader("tunetime",["TuneHifi"],band,lo_freq); } int initlength = iceil(idur[0]) + 2; return initlength; } {string,double,double}[] procedure HifiSScanModeLoadChopNoRefSequencerInit { string modeName = "load-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // inherit from fs-noref mode // spectral scans always use the full bandwidth for reference bool narrowReference = false; {string,double,double}[] retvalues = HifiPointProcLoadChopNoRefSequencerInit(naifid,ra,dec,band,reffreq,effResolution,narrowReference,hr1,hr2,wb1,wb2,data_time,n_cycles,load_interval,docommands); retvalues[1] = {"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}; return retvalues; } //////////////////////////////////// // Radial veocity correction double procedure VelCorrFreq { double lo_freq = 978200.0; // LO frequency in MHz }{ double clight = 299999.6; // light velocity in km/s // classic correction - non-relativistic // to keep time estimates constant all shifts above a reasonable // limit are ignored - all lines will still fall into the spectrometers double velmax = 30.7; double appliedvel = max(min($RADVEL,velmax),-velmax); // $RADVEL in classic definition with positive for redshifted double lo_corr = lo_freq - appliedvel * lo_freq / clight; return lo_corr; } //////////////////////////////////////////////////////////////////////// // Radiometric noise from an OTF observation // This is still to be scaled by a factor 1.0/(B_fluct*T_A) double procedure OtfRadioNoise { double x = 0.02; // integration time (everything relative to the Allan time) double xr = 0.06; // reference integration time double d1 = 0.3; // time difference between last OFF and point double d2 = 0.3; // time difference between point and next OFF }{ if(x > 0.0 && xr > 0.0) { // Auxiliary parameters double l = (d2 + 0.5 * (xr + x)) / (d1 + d2 + xr + x); double ladd = 1.0 - 2.0 * l + 2.0 * l * l; // // finally the radiometric noise double y = 1.0 / x + ladd / xr; } else { // forbid x values <=0 y = 1.0E11 * (1.0 - x); } return y; } // New implementation of the WBS zero and comb measurement // // Returns dangling transmission time // int block WBS_Zero_FCal HIFI 6014 { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency }{ // Get delays {double,string}[] result = ConfigurationReader("name_delays",["wbs_new_comb_delay"],band,lo_freq); int wbs_comb_delay = iround(result[0]{0}); int delay1 = 2; int delay2 = 3; int delay3 = wbs_comb_delay - delay1 - delay2; // Get attenuators for comb measurement {double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_att_band4_comb","hwh_att_band3_comb","hwh_att_band2_comb","hwh_att_band1_comb","hwh_att_in_comb"],band,0.0); int hwh_att_band4 = iround(result_d[0]{0}); int hwh_att_band3 = iround(result_d[1]{0}); int hwh_att_band2 = iround(result_d[2]{0}); int hwh_att_band1 = iround(result_d[3]{0}); int hwh_att_in = iround(result_d[4]{0}); // Data rate computation // The HIFI command is restricted to always read out both full WBS {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} fullreadoutparms = FrequencyCalibrationParms(true,true,false,false); // First part - zero // data rate {int,double[]} fdataparms = DataTaking(fullreadoutparms,delay1); // set data rates non_ess_hk_data_rate(fdataparms{1}[2] / 1024.0); data_rate(fdataparms{1}[0] / 1024.0); // Call command Hifi_HIFI_WBS_Calibrate($BBID,hwh_att_band4,hwh_att_band3,hwh_att_band2,hwh_att_band1,hwh_att_in); delay(delay1); // data rates for other steps fullreadoutparms = FrequencyCalibrationParms(false,true,true,true); // set data rates fdataparms = DataTaking(fullreadoutparms,delay2); non_ess_hk_data_rate(fdataparms{1}[2] / 1024.0); data_rate(fdataparms{1}[0] / 1024.0); delay(delay2); fullreadoutparms = FrequencyCalibrationParms(true,true,true,true); // set data rates fdataparms = DataTaking(fullreadoutparms,delay3); non_ess_hk_data_rate(fdataparms{1}[2] / 1024.0); data_rate(fdataparms{1}[0] / 1024.0); delay(delay3); // read-out time int readout = fdataparms{0}; // reset data rates non_ess_hk_data_rate(fdataparms{1}[1] / 1024.0); data_rate(0.0); // // additional delay for packet transmission before next zero depends // on zero duration - needs to be introduced on higher level return readout; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure SScanDoubleChop_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int grouplen = 1; // Number of frequency steps per nodding phase int n_cycles = 1; // Number of ON-OFF cycles int freqsteps = 4; // Total number of frequencies double avnumchop_on = 1.0; // Average number of ON chop cycles per frequency double avnumchop_off = 1.0; // Average number of OFF chop cycles per frequency bool fs = false; // whether frequency switch used double tscan = 60.0; // Total average duration of one cycle {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); // Use DSB noise for long spctral scans if(dsb) { double idealnoiselsb = idealvalues{1} * idealvalues{1}; double idealnoiseusb = idealvalues{3} * idealvalues{3}; double idealnoise = idealnoiselsb * idealnoiseusb / (idealnoiselsb + idealnoiseusb); } else { idealnoise = idealvalues{1} * idealvalues{1}; } double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for range coverage double accumulation = double(freqsteps) / double(nfreq); idealnoise = idealnoise * accumulation; double efficiency = idealnoise / obsnoise; // Compute the actual integration time double maxsteps = double(freqsteps * n_cycles); double posinttime = 2.0 * maxsteps * avnumchop_on * inttimeperonphase; double posofftime = 2.0 * maxsteps / double(grouplen) * avnumchop_off * inttimeperoffphase; int instrumenttime = iceil(maxsteps * tscan); // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,fs); } ///////////////////////////////////////////////////////////////////////////// // Auxiliary procedures ///////////////////////////////////////////////////////////////////////////// // Function returning generic HRS mode string[] procedure GetHrsMode_proc_fm { string[] input_hrs_mode = ["wb","wb"]; // HRS resolution mode }{ string[] output_hrs_mode = ["wb","wb"]; //Test all possible resolution modes //H-polar if(input_hrs_mode[0] == "hr" || input_hrs_mode[0] == "hr_high" || input_hrs_mode[0] == "hr_low") { output_hrs_mode[0] = "hr"; } if(input_hrs_mode[0] == "mr") { output_hrs_mode[0] = "mr"; } if(input_hrs_mode[0] == "lr") { output_hrs_mode[0] = "lr"; } //V-polar if(input_hrs_mode[1] == "hr" || input_hrs_mode[1] == "hr_high" || input_hrs_mode[1] == "hr_low") { output_hrs_mode[1] = "hr"; } if(input_hrs_mode[1] == "mr") { output_hrs_mode[1] = "mr"; } if(input_hrs_mode[1] == "lr") { output_hrs_mode[1] = "lr"; } // return output_hrs_mode; } ///////////////////////////////////////////////////////////////// // Treatment of calibration parameters for spectral scans // // Get frequency steps from long calibration table ///////////////////////////////////////////////////////////////// // First get index range {int,int} procedure GetFIndex { string band = "4a"; // HIFI band double lo_freq1 = 978200.0 in [480000.0,1950000.0]; // LO frequency double lo_freq2 = 979600.0 in [480000.0,1950000.0]; // LO frequency }{ // first step: read master file string calibfile = slookup("frequencystep_masterfile",band,"tablefile"); int iindex1 = ibracket(calibfile,"stepnumber",lo_freq1); //reduce the upper frequency by epsilon to guarantee bracketing double eps = 0.1; int iindex2 = ibracket(calibfile,"stepnumber",lo_freq2 - eps); // Exception handling int tsize = table_size(calibfile); if(iindex1 == 0 || iindex1 == tsize - 2) { IError("LO frequency " + lo_freq1 + " not covered by available range!"); } if(iindex2 == 0 || iindex2 == tsize - 2) { IError("LO frequency " + lo_freq2 + " not covered by available range!"); } else { iindex2 = iindex2 + 1; } return {iindex1,iindex2}; } //////////////////////////////////// // Fast chop DBS cross observing mode - special version for Jupiter // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcJupiterFastDBSCross { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the two raster lines int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-Jupiter-FastChop-DBS-Cross",{data_time,0,n_int_on,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer // Two changes relative to the normal DBS raster // 1) The longer load duration is enforced by zero resolution {double,double} loadResolution = {0.0,effResolution{1}}; // 2) I assume that the tuning duration does not depend on the tuning level // so that the normal pre_timing can be reused. {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(2,npoints,band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = custom_map_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSCross_post_timing(pre_timing,telescopetimes,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = custom_map_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int scansize = post_timing{1}{10}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { JupiterFastDBSRaster_commanding(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,true); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,2,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Correct for double counting of central point // The central point is returned only double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; noisevalues{4} = noisevalues{4} / multiplier; // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure DBS_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_seq = 1; // Number of continuous chop cycles int n_load = 0; // additional load measurements in one pointing phase int n_loadinterval = 10; // number of nods before a load measurement bool end_load = false; // Need for load after each pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration int shiftlength = 10; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load) { HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Second phase in first nod position // occurs for even cycle numbers runintostate = false; if(state[2] % 2 == 0) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 7) { // second nod position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i2 = 1 .. n_load) { // Use asymmetric scheme now to minimize setup uncertainties HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // First phase in second nod position // occurs for odd cycle numbers runintostate = false; if(state[2] % 2 == 1) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement // ( Does not occur if end_load is set) LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } {int,double,double,double,double,double} obs HifiSScanModeLoadChop { string modeName = "load-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-SScan-LoadChop",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanLoadChop_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,data_time_off,n_switch_on,n_switch_off,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double,double} post_timing = SScanDoubleChop_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int on_inttime = post_timing{1}{0}; int off_inttime = post_timing{1}{1}; int n_loadinterval = post_timing{1}{7}; int n_long_on = post_timing{1}{8}; int n_long_off = post_timing{1}{9}; int shiftlength = post_timing{1}{5}; int initlength = post_timing{1}{14}; bool final_load = post_timing{1}{12}; // efficiency parameters double avnumchop_on = post_timing{2}; double avnumchop_off = post_timing{3}; double tscan = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanLoadChop_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,n_total,n_loadinterval,final_load,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = SScanDoubleChop_deadtimes("lchop",band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,avnumchop_on,avnumchop_off,tscan); // // Call noise computer {double,double,double,double,double} noisevalues = SScanLoadChop_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance SScanDoubleChop_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_freq_point,n_cycles,groupnumber * n_freq_point,avnumchop_on,avnumchop_off,false,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Compute the distance of two vectors in angular coordinates // General accurate equation double procedure AngularDistance { {double,double} vector1 = {0.0,0.0}; // First vector {double,double} vector2 = {0.2,0.2}; // Second vector }{ double pideg = 3.14159265 / 180.0; double l1 = vector1{0} * pideg; double b1 = vector1{1} * pideg; double l2 = vector2{0} * pideg; double b2 = vector2{1} * pideg; double dist = acos(sin(b1) * sin(b2) + cos(b1) * cos(b2) * cos(l1 - l2)) / pideg; return dist; } //General script to read TM1, TM2,etc, procedure //Will also clear the error flags procedure LCU_Read_TM_pages_proc_aot { }{ // //It will use one single MIB TC, and clear the error flag at end Hifi_HIFI_LCU_all_tuning_hk(); // delay(1); } ////////////////////////////////////////////////////////////////// // Procedure to compute detailed pre timing for the version of the // load chop mode with baseline measurement // {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} procedure LoadChop_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_chop_on = 2 in [1,900]; // number of half load-sky-sky-load cycles on ON int n_chop_off = 2 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); CheckDataTaking(backendreadoutparms,data_time_off); int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int on_inttime = 2 * n_chop_on * data_time; int off_inttime = 2 * n_chop_off * data_time_off; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // For double phases I can use the added jitterdead in both phases for load int halfloadlength = (loadlength - jitterdead + 1) / 2; // Compare load interval and position switch interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int n_load_on = on_inttime / load_spacing; int n_load_off = off_inttime / load_spacing; // This determines the order of the loops if(load_spacing > 2 * on_inttime) { int n_per_on = n_chop_on; bool end_load_on = false; int on_pointing = on_inttime + jitterdead; } else { n_per_on = n_chop_on / (n_load_on + 1); if(n_per_on < 1) { SError("Chop phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * (n_load_on + 1) * data_time; on_pointing = on_inttime + halfloadlength + n_load_on * loadlength + jitterdead; } if(load_spacing > 2 * off_inttime) { int n_per_off = n_chop_off; bool end_load_off = false; int off_pointing = off_inttime + jitterdead; } else { n_per_off = n_chop_off / (n_load_off + 1); if(n_per_off < 1) { SError("Chop phase length on OFF position too long relative to load period."); } end_load_off = true; off_inttime = 2 * n_per_off * (n_load_off + 1) * data_time_off; off_pointing = off_inttime + halfloadlength + n_load_off * loadlength + jitterdead; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // Compute the overall cycle length // First estimate of the load interval int n_loadinterval = imax(load_interval / (on_pointing + off_pointing),1); // Exception handling for very uneven phases if(end_load_on || end_load_off) { n_loadinterval = 1; } // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {on_inttime,off_inttime,on_pointing,off_pointing,loadlength,jitterdead,load_spacing,n_loadinterval,n_per_on,n_per_off,n_load_on,n_load_off,end_load_on,end_load_off,initlength,dangling}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the OTF observing mode procedure OTFFSwitchNoRef_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int n_perline = 10; // Number of frequency switch cycles per line int n_linesperscan = 1; // Number of lines between two load holds int nlines_tot = 10; // Total number of lines to go bool end_load_on = false; // Need for load after each pointing phase int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,2,2,40,10,20,0]; // Timing of the observation from telescope int loadlength = 50; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); HIFISetHK("normal",false); // First load measurement DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 8) { // OTF integration // Check whether this is the first line if((state[2] + n_linesperscan - 1) % n_linesperscan == 0) { HIFIConfigureFSwitchIntegration(data_time,n_perline,band,lo_freq,backendreadoutparms); } HIFIFSwitchOnIntegration(data_time,n_perline,band,lo_freq,rates); runintostate = false; } if(state[0] == 6) { delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); if(state[2] * state[3] == nlines_tot) { runintostate = true; } else { runintostate = false; } } if(state[0] == 5) { // apply only if I do not come from a load-hold if(!runintostate) { delay(readoutdead); if(end_load_on) { // Perform final load measurement DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); } } runintostate = false; HIFICloseObs(); } } } // Load calibration measurement // // Most generic version for spectral scans with potentially different // frequencies for tuning and timing and retuning switch // // We might consider removing zero and comb as well - needs discussion !!! procedure SScanLoadMeasurement { string band = "4a"; // HIFI band (needed to estimate stabilization) double tuning_freq = 978200.0; // LO tuning frequency double lo_freq = 978200.0; // LO calibration frequency bool retunelo = true; // Whether LO retuning is enabled double deltanu = 1.0; // minimum effective resolution of the calibrated data int data_time = 4; // time between subsequent data readouts {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Initial computations {int,int,bool} calinit = HIFICalInit(band,lo_freq,deltanu,data_time); int used_datatime = calinit{0}; int n_inttime = calinit{1}; bool retuning = calinit{2} && retunelo; // Perform zero and comb measurement ZeroCombMeasurement(band,lo_freq,used_datatime,backendreadoutparms); // No we perform the actual hot-cold measurement // slow_chop_spectroscopy int danglingreadout = HIFI_Calibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,false); // Retune and another load if we are in HEB bands if(retuning) { // we have to wait for readout delay(danglingreadout); // Another LO vector scan at the same frequency for a stable HEB operation HIFITuneFreq(band,tuning_freq,false,""); danglingreadout = HIFI_Calibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,false); } } //////////////////////////////////// // DBS raster observing mode - Engineering version with half throw // // Return time and noise levels {int,double,double,double,double,double} obs HifiEngHalfThrowDBSRaster { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-HalfThrow-DBS-Raster",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(nlines,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { HalfDBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Procedure to compute all parameters needed in a Configure_spectroscopy {int,int,int,int,int,int,int,int,int,int,int,int,int} procedure FastConfigureSpectroscopyParams { /* Integration time */ int data_time = 10 in [4,128]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ bool wbs_used = true; // whether at least one WBS is used }{ // Get fixed parameters from configuration and calibration files // WBS delta time given by switch dead time double res = GetSkyChopDeadTime(band,lo_freq); int del_wbs = iceil(res * 1000.0); // Additional delays in the readout loops - given in OBS user manual {double,string}[] result = ConfigurationReader("name_delays",["add_hrs","add_wbs","add_jitter","wbs_readout","wbs_chunksize","tacc_add","max_hrs_phase","wbs_init","scos_jitter"],band,lo_freq); int add_hrs = iround(result[0]{0}); int add_wbs = iround(result[1]{0}); int add_jitter = iround(result[2]{0}); int wbs_readout = iround(result[3]{0}); int wbs_chunksize = iround(result[4]{0}); int tacc_add = iround(result[5]{0}); int max_hrs_phase = iround(result[6]{0}); int wbs_init = iround(result[7]{0}) + iround(result[8]{0}); // In fast chop del_hrs can be zero, but see SCR 854 int del_hrs = add_jitter; // WBS // Fixed parameter - we never split a transfer int n_wbs_integr = 1; int n_wbs1 = 2 * n_int; int n_wbs_start = n_data; // HRS is integrated up as long as the WBS int n_hrs_integr = n_int; // Split data_time into chop phases // Dead time per read out (not clear whether add_wbs applies here) int tdead_data = 2 * (wbs_readout + add_jitter) + add_wbs - add_jitter; // Initial dead time - distribute over all readouts int tdead_init = (wbs_init + n_data - 1) / n_data; int chop_phase = (1000 * data_time - tdead_data - tdead_init) / (2 * n_int); // dead time has to be an integer multiple of the 10ms chunk time int tdead_chop = del_wbs + add_jitter; int nchunk = (tdead_chop - 1) / wbs_chunksize + 1; int tcorr = nchunk * wbs_chunksize - tdead_chop; del_wbs = del_wbs + tcorr; tdead_chop = tdead_chop + tcorr; // Accumulation time int t_acc_wbs = chop_phase - tdead_chop; // discretize in 10ms chunks nchunk = (t_acc_wbs - tacc_add) / wbs_chunksize; t_acc_wbs = nchunk * wbs_chunksize + tacc_add; // HRS // Fixed parameter here int r_hrs = 1; int t_acc_hrs = t_acc_wbs - add_jitter - del_hrs - add_hrs; if(t_acc_hrs > max_hrs_phase) { SError("Chop phase length too long for HRS. Increase chop frequency."); } // How many HRS integrations possible during WBS readout int t_hrs_per = t_acc_hrs + del_wbs + add_hrs; int n_hrs_trans = wbs_readout / t_hrs_per; // This currently does not work - SCR 854: skipped n_hrs_trans = 0; // Actual integration time and dead time per readout // If WBS is used count only the WBS time if(wbs_used) { tdead_chop = tdead_chop + tacc_add; int tint_act = nchunk * wbs_chunksize * n_wbs1 * n_data; } else { tdead_chop = tdead_chop + r_hrs * add_hrs; tdead_data = tdead_data + add_jitter - 2 * (n_hrs_trans * t_hrs_per - add_jitter); tint_act = t_acc_hrs * r_hrs * (n_wbs1 + 2 * n_hrs_trans) * n_data; } // Return all config_spectroscopy timing parameters return {n_wbs_start,r_hrs,n_wbs_integr,n_hrs_integr,del_hrs,del_wbs,t_acc_wbs,t_acc_hrs,n_wbs1,n_hrs_trans,tdead_chop,tdead_data,tint_act}; } ///////////////////////////////////////////////////////////////// // Redundancy enhancement at the edges // Return increased redundancy and length of application {int,double,double} procedure GetEdgeEnhance { int redundancy = 4; // Standard redundancy of the scan string band = "4a"; // HIFI band }{ double[] edge = SpectralScanReader("fscanedge",["bandwidth","edgelength","edgeredun"],band,redundancy); int newredun = iround(edge[2]); return {newredun,edge[1],edge[0]}; } //////////////////////////////////// // OTF frequency switch observing mode without baseline calibration // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcFSwitchOTFNoRef { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-FSwitch-OTF-NoReference",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,bool,int,int} pre_timing = OTFFSwitchNoRef_pre_timing(nlines,npoints_used,band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,int} tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,bool,int,int},double,double} post_timing = OTFDoubleChopNoRef_post_timing(pre_timing,telescopetimes,nlines,data_time,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{0}; bool end_load_on = post_timing{1}{4}; int n_loadinterval = post_timing{1}{2}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFFSwitchNoRef_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on,n_loadinterval,nlines * n_cycles,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = FSwitchNoRef_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_switch_on * n_cycles,tscan,tdead); // Evaluate performance OTFDoubleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on * n_cycles,true,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // OTF frequency switch observing mode // {string,double,double}[] procedure HifiMappingProcFSwitchOTFSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = FSwitchPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities // Main loop int main_phase = iceil(phaselengths{0}); // How many lines could we do at most? int n_linesperscan_guess = main_phase / (2 * datalimit) + 1; n_linesperscan_guess = imax(n_linesperscan_guess * n_linesperscan_guess / npoints,1); // restrict the scan size if(nlines == 1 && n_linesperscan_guess > 1) { n_linesperscan_guess = 2; } else { n_linesperscan_guess = IMultiple(n_linesperscan_guess,nlines); n_linesperscan_guess = imin(n_linesperscan_guess,nlines); } int n_linesperscan_range = 1 - n_linesperscan_guess; if(n_linesperscan_range == 0) { n_linesperscan_range = 1; } double n_pointsperscan = double(n_linesperscan * npoints); // Compute back int int_time_guess = main_phase / iceil(sqrt(n_pointsperscan)); int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int n_switch_on_guess = imax(int_time_guess / (2 * data_time_guess),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } data_time_guess = imax(imin(5,int_time_guess / (2 * n_switch_on_guess)),datalimit); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * 0.67 * sqrt(n_pointsperscan) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_linesperscan",double(n_linesperscan_guess),double(n_linesperscan_range)}]; return retvalues; } // FPU Standby - CSA can be controlled - for use is chopper integrity checks. // Ensures that chopper will be commanded to zero-position // regardless of prime or redundant use. block Band0_chopper_at_zero_block_aot HIFI 6296 { string band = "0"; // HIFI band string chop_loop = "CLOSE"; // Chopper Loop status string hbb_heater = "ON" in ["ON","OFF"]; //hot source on/off }{ IError("Band0_chopper_at_zero_block_aot is deprecated. Use Init_MSA_aot instead."); } //Get true chopper angles for a chopped observation {bool,double,double} procedure GetChopVoltages { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string chop1string = "chop_M3left"; // first chopper position string chop2string = "chop_M3right"; // second chopper position }{ // get chopper angles for the two positions in prime configuration {double,string}[] result = ConfigurationReader("name_confilfpu",[chop1string,chop2string],band,lo_freq); double chop1 = result[0]{0}; double chop2 = result[1]{0}; //Check prime or redundant status {double,string}[] result_d = ConfigurationReader("name_chopper",["prime_or_redundant","p_to_r_coeff_0","p_to_r_coeff_1","p_to_r_coeff_2","prime_endstop_min","prime_endstop_max","red_endstop_min","red_endstop_max"],band,lo_freq); bool isPrime = result_d[0]{1} == "prime"; if(isPrime) { // check the chopper angle is within the ranges double endstop_min = result_d[4]{0}; double endstop_max = result_d[5]{0}; if(chop1 > endstop_max || chop1 < endstop_min) { IError("The chopper voltage (requested is " + chop1 + " V) in prime" + " mode has to be between " + endstop_min + " and " + endstop_max + " V."); } if(chop2 > endstop_max || chop2 < endstop_min) { IError("The chopper voltage (requested is " + chop2 + " V) in prime" + " mode has to be between " + endstop_min + " and " + endstop_max + " V."); } } else { //Change chopper voltage if necessary chop1 = result_d[3]{0} * pow(chop1,2.0) + result_d[2]{0} * chop1 + result_d[1]{0}; chop2 = result_d[3]{0} * pow(chop2,2.0) + result_d[2]{0} * chop2 + result_d[1]{0}; //Now check the chopper angle is within the ranges endstop_min = result_d[6]{0}; endstop_max = result_d[7]{0}; if(chop1 > endstop_max || chop1 < endstop_min) { IError("The chopper voltage (requested is " + chop1 + " V) in redundant" + " mode has to be between " + endstop_min + " and " + endstop_max + " V."); } if(chop2 > endstop_max || chop2 < endstop_min) { IError("The chopper voltage (requested is " + chop2 + " V) in redundant" + " mode has to be between " + endstop_min + " and " + endstop_max + " V."); } } return {isPrime,chop1,chop2}; } //Configure backends procedure ConfigureBackend { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} }{ //HRS configuration: //1. Resolution mode string hrs_mode_h = "hr"; if(hrs1{0}) { if(hrs1{1} == 1) { // medium resolution hrs_mode_h = "mr"; } if(hrs1{1} == 2) { // low resolution hrs_mode_h = "lr"; } if(hrs1{1} == 3) { // wide-band resolution hrs_mode_h = "wb"; } } string hrs_mode_v = "hr"; if(hrs2{0}) { if(hrs2{1} == 1) { // medium resolution hrs_mode_v = "mr"; } if(hrs2{1} == 2) { // low resolution hrs_mode_v = "lr"; } if(hrs2{1} == 3) { // wide-band resolution hrs_mode_v = "wb"; } } // string[] hrs_mode = [hrs_mode_h,hrs_mode_v]; HRS_config_resol_block_aot(band,hrs_mode); // //2. Internal LO + attenuator set to max. double if_centre = 6.0; double[] hrsH_LO = [if_centre + hrs1{2}[0] / 1000.0,if_centre + hrs1{2}[1] / 1000.0,if_centre + hrs1{2}[2] / 1000.0,if_centre + hrs1{2}[3] / 1000.0]; double[] hrsV_LO = [if_centre + hrs2{2}[0] / 1000.0,if_centre + hrs2{2}[1] / 1000.0,if_centre + hrs2{2}[2] / 1000.0,if_centre + hrs2{2}[3] / 1000.0]; // HRS_config_att_lo_block_aot(band,hrs_mode,hrsH_LO,hrsV_LO); // //WBS configuration: set all attenuators to max. Maybe superfluous WBS_config_block_aot(band); // } // Zero measurement with nominal selection // This should turn into a single command when SCR 743 is solved int block WBS_Full_Zero HIFI 6003 { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency int data_time = 4; // time between subsequent data readouts {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // data rate and read-out time {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int readout = dataparms{0}; // work-around for SCR 607 // put the zero switch on Hifi_HIFI_Single_cmd($BBID,"HWH_ZERO_ON"); Hifi_HIFI_Single_cmd($BBID,"HWV_ZERO_ON"); // Unfortunately we loose 1s here due to the additional commands delay(1); // send the configure spectroscopy command to configure the measurement // returned dead times not needed here ConfigureSpectroscopy(data_time,1,"tp",band,lo_freq,backendreadoutparms); // set data rates non_ess_hk_data_rate(dataparms{1}[2] / 1024.0); data_rate(dataparms{1}[0] / 1024.0); // execute a total power measurement with the zero switch on Hifi_HIFI_Spectr_total_power($BBID); delay(data_time); // reset data rates non_ess_hk_data_rate(dataparms{1}[1] / 1024.0); data_rate(0.0); // put zero off Hifi_HIFI_Single_cmd($BBID,"HWH_ZERO_OFF"); Hifi_HIFI_Single_cmd($BBID,"HWV_ZERO_OFF"); // We loose again 1s here due to the additional commands delay(1); // This is reduced due to the SCR 607 overhead in the buidling block readout = readout - 1; return readout; } ///////////////////////////////////////////////////////////////// // Procedure to translate levels into strings string[] procedure TargetNames { string band = "4a"; // HIFI band double lo_freq = 978200.0; // reference LO frequency in MHz bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS target levels }{ // Get target limits double[] limits = CalibrationReader("attenuator_levels",["sscan_max","sscan_min","sscan_high","sscan_normal","sscan_low"],band,lo_freq); // Criteria for the table setup double halfwidth = limits[2] - limits[4]; // Output field string[] target = []; int nfreq = length(targetlevels); // Check for retuning needs if(retuning) { // Construct table of actual target levels from differences double oldtarget = targetlevels[0]; double step = 0.0; int oldindex = 0; target[0] = ""; for(int jjj = 1 .. nfreq - 1) { target[jjj] = ""; step = targetlevels[jjj] - oldtarget; if(abs(step) > halfwidth) { if(step > 0.0) { target[oldindex] = "sscan_low"; } else { target[oldindex] = "sscan_high"; } oldtarget = targetlevels[jjj]; oldindex = jjj; } // Final tuning if(step > 0.0) { target[oldindex] = "sscan_low"; } else { target[oldindex] = "sscan_high"; } } } else { // No retuning needed // search again for minimum - use for target level double absmin = arraymin(targetlevels); if(limits[0] - absmin < halfwidth) { target[0] = "sscan_normal"; } else { if(targetlevels[0] > limits[3]) { if(targetlevels[0] > limits[2]) { target[0] = "sscan_max"; } else { target[0] = "sscan_high"; } } else { if(targetlevels[0] < limits[4]) { target[0] = "sscan_min"; } else { target[0] = "sscan_low"; } } } // Fill the table with empty values for(int jjjj = 1 .. nfreq - 1) { target[jjjj] = ""; } } // table with either a single entry or entries at tuning points return target; } // Flexible WBS attenuator tuning block with variable target // Both polarizations are treated block WBS_attenuators_block HIFI 6613 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency string target_name = "normal"; // Name of target level bool oncold = false; // Whether we are on cold intead of HBB }{ double[] cresult = CalibrationReader("attenuator_levels",[target_name],band,lo_freq); double target_value = cresult[0]; // Correct value in case of cold LOS instead of HBB if(oncold) { // Get involved temperatures double tsys = InterpolateTsys(band,1000.0 * lo_freq); {double,double} tloads = LoadTemperatures(band,1000.0 * lo_freq); double hotlevel = tsys + tloads{0}; double coldlevel = tsys + tloads{1}; target_value = target_value * coldlevel / hotlevel; } else { RotateChopper(band,lo_freq,"chop_hot"); delay(1); } //Now tune attenuators. int tune_target = iround(100.0 * target_value); Hifi_HIFI_Tune_WBS($BBID,tune_target); //Get delay {double,string}[] result_d = ConfigurationReader("name_delays",["wbs_tune_delay"],band,lo_freq); int wbs_tune_delay = iround(result_d[0]{0}); delay(wbs_tune_delay); } ///////////////////////////////////////////////////////////////// // Spectral scan in frequency switch without OFF calibration // {string,double,double}[] procedure HifiSScanProcFSwitchNoRefSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // nherit from load-chop mode {string,double,double}[] retvalues = HifiSScanProcLoadChopNoRefSequencerInit(naifid,ra,dec,band,lo_freq,lo_freq_up,redundancy,effResolution,wbs1Used,wbs2Used,data_time,n_cycles,n_freq_point,load_interval,docommands); return retvalues; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF observing mode {int,{int,int,int,int,int,int,int,int},double,double} procedure OTFmap_post_timing { {int,int,int,int,int,int,int,int} pre_timing = {10,1,12,13,21,10,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,2,2,40,10,20,21,0]; int data_time = 4; // chunk size given by the data rates and optimum speed int n_linesperscan = 1; // Number of lines between two OFFs int n_cover = 1; // Number of map coverages int load_interval = 1800; // load period = f(band,lo_freq,eff_resolution{1}) }{ // Get all values from the pre_timing section int n_pp = pre_timing{0}; int n_scans = pre_timing{1}; int off_inttime = pre_timing{2}; int off_pointing = pre_timing{3}; int loadlength = pre_timing{4}; int n_loadinterval = pre_timing{5}; int initlength = pre_timing{6}; int dangling = pre_timing{7}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[6]; // Slew time to OFF int longslew = telescopetimes[7]; // Actual slew time for load slew int tturn = telescopetimes[5]; // Turn around between lines int tline = telescopetimes[4]; // Time in line int tend = telescopetimes[8]; // Final deceleration time // The telescope slew can be a bit further than requested int line_inttime = n_pp * data_time; int line_time = line_inttime; if(tline != line_time) { if(tline < line_time) { CError("OTF scan length returned by telescope too short for instrument."); } else { line_time = tline; } } // Now compute the real scan time and the real load interval int scan_time = n_linesperscan * line_time + (n_linesperscan - 1) * tturn + 2 * slewtime + off_pointing; // Check for reasonable scan times if(scan_time > load_interval) { IError("Scan duration too long for required load period. " + "Reduce the map size or increase the step size."); } // Finally I can compute the actual load interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength + slewtime,scan_time); n_loadinterval = load_spacing / scan_time; n_loadinterval = imin(n_loadinterval,32); // Make sure that load slews occur at the same position in each coverage n_loadinterval = IMultiple(n_loadinterval,n_scans); // Compute duration of measurement int tdead = imax(loadlength,slewtime); int normal_scan_time = n_linesperscan * line_time + (n_linesperscan - 1) * tturn + 2 * slewtime + off_pointing; int load_scan_time = n_linesperscan * line_time + (n_linesperscan - 1) * tturn + slewtime + tdead + off_pointing; int n_tot = n_scans * n_cover; int n_load = n_tot / n_loadinterval; int maptime = (n_tot - n_load) * normal_scan_time + n_load * load_scan_time; // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); int totaltime = maptime + off_pointing + dangling + tend; // Average dead and scan time for drift estimate double tscan = double(maptime) / double(n_tot); // Get pointing dead time, instrument dead time is added later double avdead = tscan - double(n_linesperscan * line_inttime + off_inttime); // show gyro-propagation messages GCPMessages(off_pointing,load_scan_time,tend); // Return all the times needed in the observing mode modules return {totaltime,{n_pp,n_scans,off_inttime,off_pointing,loadlength,n_loadinterval,initlength,dangling},tscan,avdead}; } //////////////////////////////////// // Load chop mode without baseline calibration // // The implementation now assumes that the corresponding Herschel // pseudo-pointing mode will be available // {int,double,double,double,double,double} obs HifiPointProcLoadChopNoRef { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-LoadChop-NoReference",{data_time,0,0,0,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,bool,int,int} pre_timing_f = LoadChopNoRef_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,pre_timing_f); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing_f = SingleChopNoRef_post_timing(pre_timing_f,telescopetimes); // Now the actual observation starts // Prepare telescope command tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,post_timing_f{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Consistency check int totaltime = post_timing_f{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// // standard parameters for fine pointing int loadlength = post_timing_f{1}{2}; int n_per_on = post_timing_f{1}{4}; int n_load_on = post_timing_f{1}{5}; bool end_load_on = post_timing_f{1}{6}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { LoadChopNoRef_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on,n_load_on,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // There are no telescope dead times involved in this mode {double,double,double} tact = SingleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_per_on * (n_load_on + 1),tscan,tdead); // Evaluate performance SingleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_per_on * (n_load_on + 1),false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {string,double,double}[] procedure HifiPointModeFSwitchSequencerInit { string modeName = "fs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_switch_off = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = FSwitchPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_guess = imax(iceil(phaselengths{0} / (2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; new_data_time = MatchMinPointing(data_time_off_guess,data_time_off_range,2 * n_switch_off_guess); data_time_off_guess = new_data_time{0}; data_time_off_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)}]; return retvalues; } {int,double,double,double,double,double} obs HifiMappingModeOTF { string modeName = "fly"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,5]; // chunk size given by the data rates and optimum speed int n_int_on = 1 in [1,1800]; // Supersamplingfactor int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-OTF",{data_time,0,n_int_on,0,n_switch_off,n_linesperscan,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,data_time * n_int_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,int,int,int,int} pre_timing = OTFmap_pre_timing(nlines,npoints_used,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_linesperscan,n_switch_off,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_with_off_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int},double,double} post_timing = OTFmap_post_timing(pre_timing,telescopetimes,data_time,n_linesperscan,n_cycles,load_interval); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_with_off_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int n_pp = post_timing{1}{0}; int n_scans = post_timing{1}{1}; int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{5}; double tscan = post_timing{2}; double tdead = post_timing{3}; // telescope time int slewtime = telescopetimes[6]; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFmap_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,nlines * n_cycles,n_linesperscan,n_switch_off,n_pp,n_loadinterval,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check]) int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = OTFmap_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_linesperscan,n_switch_off,n_pp,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = OTFmap_noisecomputer(band,lo_freq,effResolution,oneGHzReference,nlines,npoints_used,n_int_on,n_linesperscan,n_cycles,slewtime,tscan,tact); // Evaluate performance OTF_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_scans,n_cycles,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // HRS attenuator tuning, block // Both polarizations are treated block HRS_tune_block_aot HIFI 6601 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band }{ //Now tune attenuators: it sets the HRS to ultra_wide Hifi_HIFI_Tune_HRS($BBID); //Get delay {double,string}[] result_d = ConfigurationReader("name_delays",["hrs_tune_delay"],band,0.0); int hrs_tune_delay = iround(result_d[0]{0}); delay(hrs_tune_delay); // } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double,double,double} procedure DoubleChop_deadtimes { string chopmode = "chop" in ["chop","lchop","fs"]; // chop mode string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval on ON int data_time_off = 4; // data dump interval on OFF int n_chop_on = 3; // number of chop cycles in one integration on ON int n_chop_off = 3; // number of chop cycles in one integration on OFF int n_load_on = 0; // number of integrations on ON -1 int n_load_off = 0; // number of integrations on OFF -1 double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get values for ON integration {double,double} tinst = GetInstDeadSlowChop(data_time,2 * n_chop_on,chopmode,band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * 2 * n_chop_on) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdeadint = tdeadint - double(n_chop_on) * tinst{1}; // add to total dead time double tdead_tot = tdead + double(n_load_on + 1) * tdeadint; double tswitch_on = tinst{1}; double tphaseint_on = tinst{0} / double(2 * n_chop_on); // OFF integration tinst = GetInstDeadSlowChop(data_time_off,2 * n_chop_off,chopmode,band,lo_freq,backendreadoutparms); // dead time tdeadint = double(data_time_off * 2 * n_chop_off) - tinst{0}; // subtract dead times in switches tdeadint = tdeadint - double(n_chop_off) * tinst{1}; // add to total dead time tdead_tot = tdead_tot + double(n_load_off + 1) * tdeadint; double tswitch_off = tinst{1}; double tphaseint_off = tinst{0} / double(2 * n_chop_off); // Return total dead time and the dead times in the two chops return {tdead_tot,tphaseint_on,tphaseint_off,tswitch_on,tswitch_off}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure LoadChopNoRef_FCal_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval limited by the data rates int n_per_on = 2; // number of half load-sky-sky-load cycles on ON int n_load_on = 0; // additional load measurements in ON pointing phase bool end_load_on = false; // Need for load after ON pointing phase int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,0]; // Timing of observation from telescope int loadlength = 21; // Load duration }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement_FCal(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // ON integration HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load_on) { HIFILoadChopOnIntegration(data_time,n_per_on,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement_FCal(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFILoadChopOnIntegration(data_time,n_per_on,band,lo_freq,rates); } if(state[0] == 5) { delay(readoutdead); if(end_load_on) { // Perform final load measurement LoadMeasurement_FCal(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } HIFICloseObs(); } } } //Set HIFI to primary mode, mode //In practice, it sets LOU in nominal mode with no channel selected obs HifiEngSetIntoPrimary { }{ // pre_timing {int,int} pre_timing = Eng_pre_timing(); int initlength = pre_timing{0}; int closelength = pre_timing{1}; int mainduration = duration(HifiIntoPrimary()); // telescope command int[] ts = no_pointing(true,initlength,closelength,mainduration); }{ // Instrument commanding - use state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 2) { // Initialization HIFIInitObs(); HIFISetHK("fast",true); } if(state[0] == 3) { // switch to nominal settings HifiIntoPrimary(); } if(state[0] == 5) { HIFISetHK("normal",true); HIFICloseObs(); } } } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure OTFDoubleChop_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int nlines = 20; // Number of lines in the map int npoints = 20; // Number of points in the map int n_switch_on = 1; // Supersamplingfactor int n_switch_off = 3; // Number of data dumps for the OFF integration time int n_scans = 2; // Number of OTF scans to cover the map int n_cycles = 1; // Number of map coverages bool fs = false; // whether frequency switch used double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for map coverage idealnoise = idealnoise * double(npoints * nlines); double efficiency = idealnoise / obsnoise; // Compute the actual integration time double posinttime = double(n_cycles * nlines * npoints * 2 * n_switch_on) * inttimeperonphase; double posofftime = double((n_cycles * n_scans + 1) * 2 * n_switch_off) * inttimeperoffphase; int instrumenttime = iceil(double(n_cycles * n_scans) * tscan + double(2 * n_switch_off) * inttimeperoffphase); // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // Non-standard messages message("

"); message("The observed map consists of " + nlines + " OTF lines, each covering " + npoints + " readout points.
"); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,fs); } ///////////////////////////////////////////////////////////////// // Spectral scan in load-chop with OFF calibration // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiSScanProcLoadChop { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-SScan-LoadChop",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanLoadChop_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,data_time_off,n_switch_on,n_switch_off,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double,double} post_timing = SScanDoubleChop_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int on_inttime = post_timing{1}{0}; int off_inttime = post_timing{1}{1}; int n_loadinterval = post_timing{1}{7}; int n_long_on = post_timing{1}{8}; int n_long_off = post_timing{1}{9}; int shiftlength = post_timing{1}{5}; int initlength = post_timing{1}{14}; bool final_load = post_timing{1}{12}; // efficiency parameters double avnumchop_on = post_timing{2}; double avnumchop_off = post_timing{3}; double tscan = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanLoadChop_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,n_total,n_loadinterval,final_load,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = SScanDoubleChop_deadtimes("lchop",band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,avnumchop_on,avnumchop_off,tscan); // // Call noise computer {double,double,double,double,double} noisevalues = SScanLoadChop_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance SScanDoubleChop_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_freq_point,n_cycles,groupnumber * n_freq_point,avnumchop_on,avnumchop_off,false,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////////////////////////////////////////// // Radiometric noise from an asymmetric two-phase observation // This is still to be scaled by a factor 1.0/(B_fluct_A*T_Allan) double procedure AsymmetricRadioNoise { double xa = 0.1; // integration time in phase A relative to Allan time double xb = 0.1; // integration time in phase B relative to Allan time double resrat = 1.0; // Ratio in the effective resolution B/A }{ if(xa > 0.0) { double y = 1.0 / xa + 1.0 / (xb * resrat); } else { // forbid x values <=0 y = 1.0E11 * (1.0 - xa); } return y; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure SingleChop_deadtimes { string chopmode = "chop" in ["chop","lchop","fs"]; // chop mode string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval int n_chop = 3; // number of chop cycles in one integration }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get values for ON integration {double,double} tinst = GetInstDeadSlowChop(data_time,2 * n_chop,chopmode,band,lo_freq,backendreadoutparms); // only dead times in switches count as dead time; double tdead = double(data_time * 2 * n_chop) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdead = tdead - double(n_chop) * tinst{1}; // add to total dead time double tswitch = tinst{1}; double tphaseint = tinst{0} / double(2 * n_chop); // Return total dead time and the dead times in the two chops return {tdead,tphaseint,tswitch}; } ////////////////////////////////////////////////////////////////////// // Generic procedure to determine backend parameters for a // Configure_spectroscopy command {int,int,int,int,int[],int[],string} procedure ConfigSpectroscopyBackends { /* Integration time */ int data_time = 4; // Integration time between two data readouts /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands}, WBS1/2 {used, channel windows} }{ // The following parameters are hard-wired here as they should never change int wbs16bitlimit = 5; int wbs16bitrshift1 = 1; int wbs16bitrshift2 = 2; int wbs24bitrshift0 = 20; int wbs24bitrshift1 = 40; int wbs24bitrshift2 = 80; int hrsrshift0 = 16; int hrsrshift1 = 32; int hrsrshift2 = 64; // Compute transfer mode // 16 bit format for short integrations if(data_time <= wbs16bitlimit) { string packing = "16_bits_format"; // Right shift depends in data_time if(data_time <= wbs16bitrshift1) { int wbs_rshift = 1; } else { if(data_time <= wbs16bitrshift2) { wbs_rshift = 2; } else { wbs_rshift = 3; } } // 24 bit mode for long integrations } else { packing = "24_bits_format"; // Right shift to produce valid IF power HK data if(data_time <= wbs24bitrshift0) { wbs_rshift = 0; } else { if(data_time <= wbs24bitrshift1) { wbs_rshift = 1; } else { if(data_time <= wbs24bitrshift2) { wbs_rshift = 2; } else { wbs_rshift = 3; } } } } // bit shift for HRS if(data_time <= hrsrshift0) { int hrs_rshift = 0; } else { if(data_time <= hrsrshift1) { hrs_rshift = 1; } else { if(data_time <= hrsrshift2) { hrs_rshift = 2; } else { hrs_rshift = 3; } } } // Backend selection // HRS {int,int,int,int} hrssets = HrsSubbandSelection(backendreadoutparms); int hrsh_sel = hrssets{0}; int hrsv_sel = hrssets{1}; // WBS windows // WBS-H // Initialize to zero int[] wbsh_pars = [0,0,2048,0,4096,0,6144,0]; if(backendreadoutparms{2}{0}) { // Set defined boundaries wbsh_pars[0] = backendreadoutparms{2}{1}[0][0] + wbsh_pars[0]; wbsh_pars[1] = backendreadoutparms{2}{1}[0][1] - backendreadoutparms{2}{1}[0][0]; wbsh_pars[2] = backendreadoutparms{2}{1}[1][0] + wbsh_pars[2]; wbsh_pars[3] = backendreadoutparms{2}{1}[1][1] - backendreadoutparms{2}{1}[1][0]; wbsh_pars[4] = backendreadoutparms{2}{1}[2][0] + wbsh_pars[4]; wbsh_pars[5] = backendreadoutparms{2}{1}[2][1] - backendreadoutparms{2}{1}[2][0]; wbsh_pars[6] = backendreadoutparms{2}{1}[3][0] + wbsh_pars[6]; wbsh_pars[7] = backendreadoutparms{2}{1}[3][1] - backendreadoutparms{2}{1}[3][0]; } // WBS-V // Initialize to zero int[] wbsv_pars = [0,0,2048,0,4096,0,6144,0]; if(backendreadoutparms{3}{0}) { // Set defined boundaries wbsv_pars[0] = backendreadoutparms{3}{1}[0][0] + wbsv_pars[0]; wbsv_pars[1] = backendreadoutparms{3}{1}[0][1] - backendreadoutparms{3}{1}[0][0]; wbsv_pars[2] = backendreadoutparms{3}{1}[1][0] + wbsv_pars[2]; wbsv_pars[3] = backendreadoutparms{3}{1}[1][1] - backendreadoutparms{3}{1}[1][0]; wbsv_pars[4] = backendreadoutparms{3}{1}[2][0] + wbsv_pars[4]; wbsv_pars[5] = backendreadoutparms{3}{1}[2][1] - backendreadoutparms{3}{1}[2][0]; wbsv_pars[6] = backendreadoutparms{3}{1}[3][0] + wbsv_pars[6]; wbsv_pars[7] = backendreadoutparms{3}{1}[3][1] - backendreadoutparms{3}{1}[3][0]; } // return {wbs_rshift,hrs_rshift,hrsh_sel,hrsv_sel,wbsh_pars,wbsv_pars,packing}; } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for a // Spectral Scan DBS observing mode // // We currently assume that each nodding motion is related to an // instrument calibration. This may be an efficiency limitation if // more calibration measurements are needed. Then the loop sequence // should be changed. // // This implementation assumes that the whole scan can be performed // with a single pointing command. If the system temperature varies // too much so that it cannot be compensated by a slight change of // the redundancy, the scan has to be split into several calls of this // mode. // {{int,int,int,int,int,int,int,int,int,bool,int,int,int},{int,double,double[],int[][],bool,double[],int,bool}} procedure FastSScanDBS_pre_timing { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 1 in [1,1800]; // number of data transfer cycles per pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Create composite readout structure for backends {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First check the group length // The default frequency group length is given by n_freq_point. // It is derived in the sequencer using // GetFNoCalibLength(band,ref_freq); // For n_cycles>1 it has to be unity, everything else is rejected // We rely on the sequencer to determine the best group length if(n_cycles > 1 && n_freq_point > 1) { SError("Only frequency group length 1 allowed for cycle numbers > 1."); } // Get frequency grid characteristic parameters {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq_low,lo_freq_up,redundancy,0.0,n_freq_point); double reffreq = fqparms{1}; double[] freqgrid = fqparms{2}; int[][] grouporder = fqparms{3}; // Process tuning level grid double[][] levelgrid = GetSScanLevelGrid(band,wbs1,wbs2,freqgrid,fqparms{0},grouporder); {bool,double[]} targets = TargetLevels(band,reffreq,levelgrid); bool retuning = targets{0}; double[] targetgrid = targets{1}; string reftarget = ""; if(retuning) { reftarget = "sscan_normal"; } {int,double,double[],int[][],bool,double[],int,bool} spectralparms = {fqparms{0},reffreq,freqgrid,grouporder,retuning,targetgrid,fqparms{4},fqparms{5}}; ////////////////////////////////////////////////////////////////////// // Get timing within the normal DBS observations // Fixed timings in the fast-chop mode int readouttime = data_time; int jitterdead = GetMaxTimeJitter(band,reffreq); // Integration time per frequency and pointing int inttime = readouttime * n_data; // Check chopper frequency CheckFastChopFrequency(band,reffreq,data_time,n_int,n_data); // Compute load integration time int load_datatime = GetStdLoadReadout(band,reffreq); int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,eff_resolution{0},load_datatime,backendreadoutparms)); int readoutdead = FastChopReadoutDelay(band,reffreq,backendreadoutparms); loadlength = loadlength + readoutdead; // The load interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); // Duration of initial set up // Staying at the same frequency makes no sense here. // First frequency point double runningfreq = freqgrid[grouporder[0][0]]; // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,true); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,runningfreq,false); } initlength = initlength + loadlength; // Tuning delays, big tune step has to be devisable by 2 int bigtunestep = duration(HIFIRetuneFreq(band,reffreq,reftarget)); // Correct for variation within the band int tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq); bigtunestep = bigtunestep + tunediff; if(n_freq_point > 1) { int smallstep = duration(HIFIChangeFreq(band,reffreq)); } else { smallstep = bigtunestep; } // For double phases I can use the added jitterdead in both phases for tune int halftunestep = (bigtunestep - jitterdead + 1) / 2; // Check load_interval allowance int scan_time = 2 * inttime + bigtunestep; if(scan_time > load_spacing) { SError("Load interval of " + load_interval + "s is exceeded by nodding " + "period of " + scan_time + " s."); } // Rough estimate of the pointing time to issue a representative // telescope command if(n_cycles > 1) { // How often do I have to perform a load slew int n_loadinterval = imax(load_interval / scan_time,1); // fit with n_cycles n_loadinterval = imin(n_loadinterval,n_cycles); n_loadinterval = IMultiple(n_loadinterval,n_cycles); // Pointing time int pointing = inttime + jitterdead; } else { n_loadinterval = 1; pointing = n_freq_point * inttime + (n_freq_point - 1) * smallstep + halftunestep + jitterdead; } int n_bchop = n_data; // recompute load length during slews in case of short integrations // This regime must be maintained in the post_timing if(n_loadinterval <= 1) { loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,false,eff_resolution{0},load_datatime,backendreadoutparms)); loadlength = loadlength + readoutdead; } // No dangling needed in this mode - we stop halftunelength before telescope int dangling = 0; bool end_load = false; // Return all the times needed for telescope call and post_timing processing return {{inttime,pointing,readouttime,loadlength,jitterdead,load_spacing,bigtunestep,n_loadinterval,n_bchop,end_load,smallstep,initlength,dangling},spectralparms}; } // Give sequence of frequency steps in a spectral scan mode within one group int[][] procedure GetFrequencyGroupSteps { int groupsize = 3; // Number of frequencies in a group }{ // Compute limits int center = groupsize / 2; // First side stepping int[] firstside = []; int counter = 0; int i1 = center - 1; while(i1 >= 0) { firstside[counter] = i1; i1 = i1 - 1; counter = counter + 1; } i1 = groupsize - 1; while(i1 >= center) { firstside[counter] = i1; i1 = i1 - 1; counter = counter + 1; } // Second side stepping int[] secondside = []; counter = 0; i1 = center; while(i1 >= 0) { secondside[counter] = i1; i1 = i1 - 1; counter = counter + 1; } i1 = groupsize - 1; while(i1 > center) { secondside[counter] = i1; i1 = i1 - 1; counter = counter + 1; } int[][] fullseq = [firstside,secondside]; return fullseq; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF load-chop observing mode {int,int,int,int,bool,int,int} procedure OTFLoadChopNoRef_pre_timing { int nlines = 1; // Number of rows in the map int npoints = 10; // Number of data dumps per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_chop_on = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles per point int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); // jitter treatment is already taken into account by ValidMapSize // Compute parameters for the instrument timing int lineint = npoints * n_chop_on * 2 * data_time; int nlines_tot = nlines * n_cycles; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compute the scan size from the load interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength,npoints * 8); // Here, we do not know the turn around-time yet. Ignored until post_timing int n_loadinterval = load_spacing / lineint; if(n_loadinterval < 1) { SError("Scan duration too long for load period. " + "Reduce the number of chop cycles."); } // Make sure that load slews occur at the same position in each coverage CheckReasonableLineNumber(nlines,true); n_loadinterval = IMultiple(n_loadinterval,nlines); // If no load required parameter has to be 0 if(n_loadinterval > nlines_tot) { // Determine need for final load measurement double rest = double(nlines_tot % n_loadinterval) + 0.5; bool end_load_on = rest > 0.5001 * double(n_loadinterval); } else { if(n_loadinterval > nlines) { n_loadinterval = nlines; } // In all these cases a final load will be made anyway in regular pattern end_load_on = false; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,true); } initlength = initlength + loadlength; // Dangling load measurement not counted here, only dangling readout int dangling = readoutdead; // Return all the times needed in the observing mode modules // The holdlength parameter is abused for lineint here return {loadlength,load_spacing,n_loadinterval,lineint,end_load_on,initlength,dangling}; } {string,double,double}[] procedure HifiSScanModeFSwitchNoRefSequencerInit { string modeName = "fs-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // nherit from load-chop mode {string,double,double}[] retvalues = HifiSScanProcLoadChopNoRefSequencerInit(naifid,ra,dec,band,lo_freq,lo_freq_up,redundancy,effResolution,wbs1Used,wbs2Used,data_time,n_cycles,n_freq_point,load_interval,docommands); return retvalues; } // Perform frequency-switch integration at OFF position ON-OFF-OFF-ON... block HIFIFSwitchOffIntegration HIFI 6039 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_fswitch_proc_aot(data_time,n_cycle,band,lo_freq,rates); } // Noise ratio from a two-phase observation // double procedure TwoPhaseNoiseRatio { double x = 0.1; // value for integration time relative to Allan time double[] parameters = [0.3,2.5]; // Parameters: delay relative to Allan time, drift exponent }{ // Assign parameters double d = parameters[0]; double alpha = parameters[1]; // get radiometric and drift noise double yn = TwoPhaseRadioNoise(x); double yd = TwoPhaseDrift(x,d,alpha); // Compute ratio double y = yd / yn; return y; } // Configuration for slow-chop integration block HIFIConfigureSlowChopIntegration HIFI 6030 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Call procedure doing the work ConfigureSpectroscopy(data_time,2 * n_cycle,"chop",band,lo_freq,backendreadoutparms); } //////////////////////////////////////////////////////////////////////// // Noise contributions from an asymmetric double difference observation // This is still to be scaled by a factor T_cycle/(B_fluct*T_obs) {double,double} procedure DoubleDifferenceNoiseValues { double x = 0.1; // value for integration time relative to Allan time double[] parameters = [1.0,1.0,0.8,0.8,0.05,0.3,2.5,5.0,2.5]; // Parameters: ratio of integration times, ratio of effective resolutions, delay in phase1, in phase 2, between phases relative to Allan time, drift exponents }{ // Assign parameters double xrat = parameters[0]; // ratio of integration times within B/A phases double resrat = parameters[1]; // ratio of effective resolutions B/A phases double tpa = parameters[2]; // total length of A pointing phase double tpb = parameters[3]; // total length of B pointing phase double dpos = parameters[4]; // dead time within A pointing relative to system Allan double d = parameters[5]; // position switch dead time relative to differential Allan double alpha = parameters[6]; // drift exponent of system Allan double dallanrat = parameters[7]; // ratio of differential to system Allan time double dalpha = parameters[8]; // drift exponent of differential Allan // Noise from first phase double yn = TwoPhaseRadioNoise(x); double yd = TwoPhaseDrift(x,dpos,alpha); // Normalize relative to total length of pointing phase double ysumn = yn * (2.0 * x + dpos) / tpa; double ysumd = yd * (2.0 * x + dpos) / tpa; // Noise from second phase // Rescale time scales double allan_scale = pow(1.0 / resrat,1.0 / alpha); // rescale Allan yn = TwoPhaseRadioNoise(x * xrat / allan_scale); yd = TwoPhaseDrift(x * xrat / allan_scale,dpos / allan_scale,alpha); // Noise scaled with resolution // Normalize relative to total length of pointing phase ysumn = ysumn + yn / (resrat * allan_scale) * (2.0 * x * xrat + dpos) / tpb; ysumd = ysumd + yd / (resrat * allan_scale) * (2.0 * x * xrat + dpos) / tpb; // Drift between phases yd = AsymmetricDrift(tpa / dallanrat,tpb / dallanrat,d / dallanrat,dalpha); // Compensate for different Allan time scaling yd = yd / dallanrat; ysumd = ysumd + yd; return {ysumn,ysumd}; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of DBS-raster observing mode {int,int,int,int,int,int,int,int,int,int,int,int,int} procedure DBSRaster_pre_timing { int nlines_tot = 1 in [1,100]; // Number of rows in the map int npoints = 10 in [2,100]; // Number of points per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_chop = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); // Is the map size an integer multiple of the scan size? CheckReasonableLineNumber(nlines_tot * npoints,false); int scansize = n_pointsperscan; if(scansize > nlines_tot * npoints) { SError("Scan size exceeds the total map size."); } if(nlines_tot * npoints % scansize != 0) { SError("Map size is no integer multiple of the scan size."); } int n_scans = nlines_tot * npoints / scansize; // Compute parameters for the instrument timing int jitterdead = GetMaxTimeJitter(band,lo_freq); int inttime = 2 * n_chop * data_time; int readouttime = data_time; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // compute the load interval in case of short scan_time int scan_time = inttime * scansize; int n_loadinterval = imax(load_interval / (2 * scan_time),1); // Special treatment for nodding_raster due to limitations in API // Split into loads per point or per multiple points if(scansize == 1 && n_loadinterval > n_cycles) { n_loadinterval = n_cycles * (n_loadinterval / n_cycles); } n_loadinterval = imin(n_loadinterval,n_cycles * n_scans); // Compare load interval and nodding interval // This determines the order of the loops int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); // load measurements within a single point integration int n_load = inttime / load_spacing; if(n_load >= 1 && scansize > 1) { SError("Number of points in one scan too large for load period."); } // Rough estimate of the pointing time - this is corrected // after the evaluation of the telescope command if(load_spacing > 2 * scan_time) { int n_seq = n_chop; int pointing = inttime + jitterdead; } else { // It is possible that a single point is short enough, but a scan // too long. Then everything is reduced to a single point. scansize = 1; n_scans = nlines_tot * npoints; n_seq = n_chop / (n_load + 1); inttime = 2 * n_seq * (n_load + 1) * data_time; pointing = inttime + (n_load + 1) * loadlength + jitterdead; } // dangling time given by readout dead time int dangling = readoutdead; int holdlength = jitterdead; // Return all the times needed for telescope call and post_timing processing return {inttime,pointing,readouttime,loadlength,holdlength,load_spacing,n_load,n_loadinterval,n_seq,n_scans,scansize,initlength,dangling}; } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure FSwitch_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int on_inttime = 16; // Integration time per ON phase int off_inttime = 16; // Integration time per OFF phase int n_cycles = 1; // Number of half OFF-ON-ON-OFF calibration cycles double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ double tdead = tact{0}; // Average total dead time in one scan double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase double deadtimeperonphase = tact{3}; // Dead time per switch phase on ON // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Differential Allan variance allanparms = InterpolateSpecFSwitchAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double dallan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // resolution of OFF phase double sw_resolution = GetFSwitchSWResolution(band,lo_freq); double sw_resolution_lores = max(eff_resolution{1},sw_resolution); double sw_resolution_hires = max(eff_resolution{0},sw_resolution); // Compute the relative noise for the detailed timing double on_int = double(on_inttime); double off_int = double(off_inttime); // The dead time per switch might deviate between ON and OFF - ignored double deadtimeperswitch = deadtimeperonphase; // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = DoubleDifferenceNoise(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); double systemnoise_hires = DoubleDifferenceNoise(inttimeperonphase / allan_time_hires,[inttimeperoffphase / inttimeperonphase,sw_resolution_hires / eff_resolution{0},on_int / allan_time_hires,off_int / allan_time_hires,deadtimeperswitch / allan_time_hires,tdead / allan_time_hires,alpha,dallan_time_hires / allan_time_hires,dalpha]); double noiseratio = DoubleDifferenceNoiseRatio(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); // Compute total double sideband noise // Correct for signal in both pases double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 2000000.0 * double(n_cycles) * tscan)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 2000000.0 * double(n_cycles) * tscan)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } /////////////////////////////////////////////////////////////////////////// // Building blocks // // Initialize all peakup settings block HifiPeakupConfigure HIFI 6820 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number bool isH = true; // backend to use - polarization string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double stepsize = 0.0050; // Distance between subsequent points {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Translate stepsize into 1/100 arcsec int scale = iround(stepsize * 360000.0); // Determine offsets if(isH) { double[] x = CalibrationReader("peakup",["offset_y_H","offset_z_H"],band,lo_freq); int offset_y = iround(x[0]); int offset_z = iround(x[1]); } else { x = CalibrationReader("peakup",["offset_y_V","offset_z_V"],band,lo_freq); offset_y = iround(x[0]); offset_z = iround(x[1]); } // Command offsets Hifi_HIFI_configure_peakup_r1($BBID,scale,scale,offset_y,offset_z); // Call procedure for slow-chop spectroscopy configuration ConfigureSpectroscopy(data_time,2 * n_cycle,"chop",band,lo_freq,backendreadoutparms); delay(1); } // Switch on LO band - version using the slew towards a fixed point for // stabilization // assumes HIFI is prime and LO is in nominal mode obs HifiEngSwitchonLO_inslew { int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band }{ // temporarily moved from argument section to maintain compatibility with old // SOVT setup for phase3 bool robust = true; // whether the subsequent AOR is chopped+spectroscopic // First part - determine timing and telescope parameters // Fixed parameters int data_time = 4; // Data readout period {double,double} eff_resolution = {1.1,1.1}; // Native WBS resolution as goal resolution // Get reference frequency string keyfreqname = "keyfreq"; //this is for warm LO operations // "keyfreq" for cold LO operations // "keyfreq_dummy" for dummy LO operations // "midfreq" old approach double[] result_d = CalibrationReader("name_keyfreq",[keyfreqname],band,0.0); double lo_freq = result_d[0] * 1000.0; // Backend settings // standard routine from spectral scans {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,2,true,true,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; // Call specific pre_timing computer {int,int,int,int,int,int} pre_timing = SwitchOnLoadChop_pre_timing(band,lo_freq,eff_resolution,hr1,hr2,wb1,wb2,data_time,robust); // get parameters for fine pointing int totaltime = pre_timing{0}; // total duration for check int on_pointing = pre_timing{1}; // Pointing time int initlength = pre_timing{2}; // Initial setup time int dangling = pre_timing{3}; // Final load measurement int n_cycles1 = pre_timing{4}; // Number of chop cycles before retuning int n_cycles = pre_timing{5}; // Number of chop cycles after retuning // In the slew mode we rearrange the times initlength = initlength + on_pointing; on_pointing = dangling; dangling = 0; // Prepare telescope command {double,double} onPosition = {ra,dec}; // standard timing parameter list to reuse Fine_telescope procedure {int,int,int,int,int,int,bool,int,int} std_timing = {on_pointing,on_pointing,on_pointing,0,0,0,false,initlength,dangling}; {int,int,int,string,int,double,double,double,double,int} tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,std_timing); // Call telescope command int[] telescopetimes = basic_fine_pointing(true,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); }{ // Second part - instrument commanding // Get final deceleration time from the telescope section int tend = telescopetimes[2]; totaltime = totaltime + tend; // Backend settings // Create a composite readout structure {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // additional fixed parameters like in standard observing modes // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); ////////////////// // Instrument commanding sync(); int startobs = time(); // use state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization HIFIInitObs(); HIFISetHK("fast",true); // Actual switch-on // The switch will always be done at the same frequency LCU_switchon_proc_aot(band,lo_freq / 1000.0); // Initial setup and LO tuning Init_Mixing_proc_aot(band,lo_freq / 1000.0); //Deflux will do be done for bands 1 to 4 Deflux_SingleBand_proc_aot(band,lo_freq / 1000.0); // Standard backend tuning string target_name = "normal"; // Name of target level if(wb1{0} || wb2{0}) { WBS_attenuators_block(band,lo_freq / 1000.0,target_name,false); } if(hr1{0} || hr2{0}) { HRS_tune_block_aot(band); } // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); // ON integration - long hot-cold measurement if(n_cycles1 > 0) { HIFI_Calibrate_hot_cold(band,lo_freq,data_time,2 * n_cycles1,backendreadoutparms,false); HIFITuneFreq(band,lo_freq,false,""); } HIFI_Calibrate_hot_cold(band,lo_freq,data_time,2 * n_cycles,backendreadoutparms,false); } if(state[0] == 3) { delay(readoutdead); // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFICloseObs(); } } // Finalize observations // consistency check int timeTaken = time() - startobs; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } // Noise estimates could be easily added, but are not done here // in the current implementation } {int,double,double,double,double,double} obs HifiSScanModeFastDBS { string modeName = "freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-SScan-FastChop-DBS",{data_time,0,n_switch_on,n_int_on,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time / 2); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,bool,int,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = FastSScanDBS_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,n_int_on,n_switch_on,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},double,double,double} post_timing = SScanDBS_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int n_loadinterval = post_timing{1}{7}; int n_bchop = post_timing{1}{8}; int shiftlength = post_timing{1}{10}; int initlength = post_timing{1}{11}; double avnumchop = post_timing{2}; // efficiency parameters double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastSScanDBS_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_int_on,n_cycles,n_total,n_bchop,n_switch_on,n_loadinterval,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = FastSScanDBS_deadtimes(band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,n_int_on,n_bchop,n_switch_on,n_cycles,avnumchop,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = SScanDBS_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,continuumDetection,n_cycles,tscan,tact); // Evaluate performance SScanDBS_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_total,groupnumber * n_freq_point,avnumchop * double(n_int_on),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // Auxiliary function to compute the noise of an ideal instrument with // 100% observing efficiency for comparison {int,double,double,double,double,double} procedure IdealHifi { /* Setup parameters */ string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy int nlines = 1 in [1,240]; // Number of rows in the map int npoints = 10 in [1,720]; // Number of data dumps per row {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz int goalTime = 8; // Total integration time /* Sequence parameters */ bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // Get parameters which are needed double center_lo_freq = 0.5 * (lo_freq + lo_freq_up); double tsys = InterpolateTsys(band,center_lo_freq); double eta_mb = InterpolateCoupling(band,center_lo_freq); double[] gssb = InterpolateGssb(band,center_lo_freq); double phasetime = double(goalTime); double noiseratio = 0.0; // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(1.0 / (effResolution{1} * 1000000.0 * phasetime)); double dsbnoise_hires = tsys * sqrt(1.0 / (effResolution{0} * 1000000.0 * phasetime)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // return total time with initial slew int returntime = goalTime; // Originally I had added 180s from telescope // Now make corrections for maps or spectral scans if(npoints * nlines > 1) { double factor = sqrt(double(nlines * npoints)); usbnoise_lores = usbnoise_lores * factor; usbnoise_hires = usbnoise_hires * factor; lsbnoise_lores = lsbnoise_lores * factor; lsbnoise_hires = lsbnoise_hires * factor; } if(lo_freq_up > lo_freq) { {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq,lo_freq_up,redundancy,0.0,1); factor = sqrt(double(fqparms{0} / fqparms{4})); usbnoise_lores = usbnoise_lores * factor; usbnoise_hires = usbnoise_hires * factor; lsbnoise_lores = lsbnoise_lores * factor; lsbnoise_hires = lsbnoise_hires * factor; } // Return noise values and the maximum ratio of drift to radiometric noise return {returntime,usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } //Procedure to get from standby to primary mode //Concerns LO and WBS settings procedure HifiIntoPrimary { }{ //Switch LO to nominal Set_LO_Nominal_block_aot(); //Set applicable LO FDIR limits (SCR-2226) Set_LO_FDIR_temperature_block_aot(); } // Get maximum frequency switch step length double procedure GetMaxFreqThrow { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] throwlen = CalibrationReader("fsthrows",["maxfreqthrow"],band,lo_freq); return throwlen[0]; } //////////////////////////////////// // Fast chop DBS raster observing mode // {string,double,double}[] procedure HifiMappingProcFastDBSRasterSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities // Top down approach here int main_phase = iceil(phaselengths{0}); // Arbitrary selection of data_time int data_time_guess = 20; // Combine points for n_switch=1 int n_pointsperscan_guess = imin(imax(main_phase / data_time_guess,1),npoints * nlines); int n_pointsperscan_range = 1 - n_pointsperscan_guess; if(n_pointsperscan_range == 0) { n_pointsperscan_range = 1; } // remaining part for n_switch int n_switch_on_guess = main_phase / (n_pointsperscan_guess * data_time_guess) + 1; data_time_guess = main_phase / (n_pointsperscan_guess * n_switch_on_guess); // Check with data rate {int,double[]} dataparms = DataTaking(backendreadoutparms,8); int datalimit = 2 * dataparms{0}; if(data_time_guess < datalimit) { data_time_guess = datalimit; n_switch_on_guess = 1; } int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Chop phase length double phase_min = min(max(phaselengths{1},0.15),1.5); int n_int_on_guess = ifloor(double(data_time_guess) / (2.0 * phase_min)); int n_int_on_range = -n_int_on_guess / 2; if(n_int_on_range == 0) { n_int_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_pointsperscan",double(n_pointsperscan_guess),double(n_pointsperscan_range)}]; return retvalues; } // Generic A_M function for LSU setting // DT - 18 Aug 2006 int[] procedure ComputeLSU_A_M_R { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency }{ //Read parameters double[] result = CalibrationReader("name_lsu_convertion",["multiplier","f_offset","n10","n20"],band,lo_freq); double multiplier = result[0]; double f_offset = result[1]; int n10 = iround(result[2]); int n20 = iround(result[3]); // //Compute LSU frequency IN MHZ double f_lsu = lo_freq * 1000.0 / multiplier; //Compute total frequency double f_total = f_lsu + f_offset; //Compute parameter n int n = ifloor(15.0 * (f_total / 1.875 - double(ifloor(f_total / 1.875)))); //Compute main and offset loop parameters int n1 = n10 + n; // offset loop int d1 = 15; //offset loop int n2 = iround(abs(double(n20 - ifloor(f_total / 1.875) + n))); //main loop int d2 = 16; // //Compute A,M and R parameters for main and offset loop int m1 = ifloor(double(n1) / 10.0) - 1; // offset loop int a1 = n1 - 10 * ifloor(double(n1) / 10.0); // offset loop int r1 = d1 - 1; // offset loop int m2 = ifloor(double(n2) / 10.0) - 1; // main loop int a2 = n2 - 10 * ifloor(double(n2) / 10.0); // main loop int r2 = d2 - 1; // main loop // int[] lsu_a_m_r_parameter = [0,0,0,0,0,0]; lsu_a_m_r_parameter[0] = m1; lsu_a_m_r_parameter[1] = a1; lsu_a_m_r_parameter[2] = r1; lsu_a_m_r_parameter[3] = m2; lsu_a_m_r_parameter[4] = a2; lsu_a_m_r_parameter[5] = r2; // //Conversion into main and offset LSU word int main_word = iround(pow(2.0,18.0) * double(ifloor(double(r2) % pow(2.0,6.0) / pow(2.0,4.0))) + pow(2.0,15.0) * double(ifloor(double(m2) % pow(2.0,9.0) / pow(2.0,7.0))) + pow(2.0,8.0) * (double(m2) % pow(2.0,9.0)) + pow(2.0,4.0) * (double(r2) % pow(2.0,6.0) % pow(2.0,4.0)) + double(a2) % pow(2.0,4.0)); int offset_word = iround(pow(2.0,18.0) * double(ifloor(double(r1) % pow(2.0,6.0) / pow(2.0,4.0))) + pow(2.0,15.0) * double(ifloor(double(m1) % pow(2.0,9.0) / pow(2.0,7.0))) + pow(2.0,8.0) * (double(m1) % pow(2.0,9.0)) + pow(2.0,4.0) * (double(r1) % pow(2.0,6.0) % pow(2.0,4.0)) + double(a1) % pow(2.0,4.0)); // //debug_print("LSU conversion result " + lsu_a_m_r_parameter); //debug_print("main: " + main_word + ", offset: " + offset_word); // //Compute real LO frequency set by A,M,R combination double nn1 = double(10 * (m1 + 1) + a1); double dd1 = double(r1 + 1); double nn2 = double(10 * (m2 + 1) + a2); double dd2 = double(r2 + 1); double flsu_back = 24000.0 + 30.0 * (nn1 / dd1 + nn2 / dd2); if(band == "2a" || band == "3b") { flsu_back = 24000.0 + 30.0 * (nn1 / dd1 - nn2 / dd2); } double flo_back = flsu_back * multiplier; //debug_print("Real tuned frequency: " + flo_back); // int[] resu = [0,0]; resu[0] = main_word; resu[1] = offset_word; //Modification following SPR-1302 resu = [resu[0] + 0xf2200000,resu[1] + 0xf2300000]; // return resu; } // Slow chop integration at OFF position ON-OFF-OFF-ON... block HIFIHalfChopOffIntegration HIFI 6052 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3","chop_M3right"],rates); } // Noise ratio from an OTF line for the special case of a // multiple scan of the same line // double procedure OtfRepeatedNoiseRatio { double num_scans = 2.0; // number of scans of the same line double n = 10.0; // number of points in one scan double[] parameters = [0.02,0.4,0.05,0.667,2.5]; // Parameters: integration time, delay and turn-around relative to Allan time, ratio of t_off time to sqrt(n)*t_on, line length, drift exponent }{ // Assign parameters double x = parameters[0]; double d = parameters[1]; double doff = parameters[2]; double qval = parameters[3]; double alpha = parameters[4]; // Make corrections for different calibration double qcorr = qval * sqrt(num_scans); {double,double} noisevalues = OtfNoiseValues(num_scans * n,[x,d,doff,qcorr,alpha]); double yn = noisevalues{0}; yn = yn / num_scans; double yd = noisevalues{1}; // Compute ratio double y = yd / yn; return y; } ////////////////////////////////////////////////////////// // Commanding procedures: 1:1 copy from normal raster // Procedure to generate the instrument commands for the DBS raster mode procedure HalfDBSRaster_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_seq = 1; // Number of continuous chop cycles int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles int n_pointsperscan = 1; // Number of points measured before moving to the second pointing phase int n_loadinterval = 10; // number of nods before a load measurement int n_load = 0; // additional load measurements in one pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,0,10,20,21,0,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration bool iscross = false; // Whether we use a cross instead of a raster }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get all values from the telescope section int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Count phases by hand to allow simultaneous usage by Raster and Cross int iphase = 0; // There is no nod counter in the return values - count this by hand int inod = 0; // Do I have to make loads in short nods and subsequent holds? if(iscross) { bool holdforload = n_pointsperscan > 1; } else { holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles; } //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; iphase = iphase + 1; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles // The use of n_load differs by 1 from the other observing modes here for(int i1 = 1 .. n_load - 1) { HIFIHalfChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFIHalfChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: // n_pointsperscan=1, n_loadinterval > n_cycles if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } // Update phase counter iphase = iphase + 1; } // Second pointing phase if(state[0] == 7) { // second nod position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); for(int i2 = 1 .. n_load - 1) { HIFIHalfChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFIHalfChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } // Update phase counter iphase = iphase + 1; } // Load nod if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } // Hold if(state[0] == 6) { // finished shift of instrument operations relative to pointing command runintostate = false; } // Final load if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } ///////////////////////////////////////////////////////////////// // Spectral scan in frequency switch with OFF calibration // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiSScanProcFSwitch { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-SScan-FSwitch",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanFSwitch_pre_timing(band,lo_freq,lo_freq_up,redundancy,freq_throw,effResolution,hr1,hr2,wb1,wb2,data_time,data_time_off,n_switch_on,n_switch_off,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double,double} post_timing = SScanDoubleChop_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int on_inttime = post_timing{1}{0}; int off_inttime = post_timing{1}{1}; int n_loadinterval = post_timing{1}{7}; int n_long_on = post_timing{1}{8}; int n_long_off = post_timing{1}{9}; int shiftlength = post_timing{1}{5}; int initlength = post_timing{1}{14}; bool final_load = post_timing{1}{12}; // efficiency parameters double avnumchop_on = post_timing{2}; double avnumchop_off = post_timing{3}; double tscan = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanFSwitch_commanding(band,reffreq,freq_throw,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,n_total,n_loadinterval,final_load,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = SScanDoubleChop_deadtimes("fs",band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,avnumchop_on,avnumchop_off,tscan); // // Call noise computer {double,double,double,double,double} noisevalues = SScanFSwitch_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance SScanDoubleChop_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_freq_point,n_cycles,groupnumber * n_freq_point,avnumchop_on,avnumchop_off,true,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } procedure IError { string errormessage = "Bad parameter combination."; // Error message }{ string fullmessage = "Invalid input parameter setting:
" + errormessage + "
Please, change your AOR parameters."; error(fullmessage); } /////////////////////////////////////////////////////////////////////////////// // Subroutine for HRS settings shared between ConfigSpectroscopy and DataTaking {int,int,int,int} procedure HrsSubbandSelection { /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands}, WBS1/2 {used, channel windows} }{ // Seection of HRS subbands in corect order int[] widebits = [129,66,36,24]; int[] lowbits = [192,48,12,3]; int[] normalbits = [240,15]; int[] highbits = [255]; // HRS-H int hrsh_sel = 0; int n_hchannels = 0; if(backendreadoutparms{0}{0} == true) { // normal resolution int maxbands = 2; int[] bits = normalbits; int n_perband = 2064; if(backendreadoutparms{0}{1} > 2) { // wide resolution maxbands = 4; bits = widebits; n_perband = 1032; } else { if(backendreadoutparms{0}{1} > 1) { // low resolution maxbands = 4; bits = lowbits; n_perband = 1032; } else { if(backendreadoutparms{0}{1} < 1) { // high resolution maxbands = 1; bits = highbits; n_perband = 4128; } } } for(int i0 = 0 .. maxbands - 1) { if(backendreadoutparms{0}{2}[i0]) { hrsh_sel = hrsh_sel + bits[i0]; n_hchannels = n_hchannels + n_perband; } } } // HRS-V int hrsv_sel = 0; int n_vchannels = 0; if(backendreadoutparms{1}{0} == true) { // normal resolution maxbands = 2; bits = normalbits; n_perband = 2064; if(backendreadoutparms{1}{1} > 2) { // wide resolution maxbands = 4; bits = widebits; n_perband = 1032; } else { if(backendreadoutparms{1}{1} > 1) { // low resolution maxbands = 4; bits = lowbits; n_perband = 1032; } else { if(backendreadoutparms{1}{1} < 1) { // high resolution maxbands = 1; bits = highbits; n_perband = 4128; } } } for(int i1 = 0 .. maxbands - 1) { if(backendreadoutparms{1}{2}[i1]) { hrsv_sel = hrsv_sel + bits[i1]; n_vchannels = n_vchannels + n_perband; } } } return {hrsh_sel,hrsv_sel,n_hchannels,n_vchannels}; } // Wrapper for fixed instrument configurations. // // This is used for the COLD instrument - in-orbit configuration // {double,string}[] procedure ConfigurationReader { string topicname = "name_confilfpu"; // Name of entry in master file string[] objectnames = ["bias_standby_h"]; // Names of calibration objects to be read string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ string mainmasterfile = "configuration_masterfile"; {double,string}[] retvalues = FlexibleConfigurationReader(mainmasterfile,topicname,objectnames,band,lo_freq); return retvalues; } {int,double,double,double,double,double} obs HifiPointModeDBS { string modeName = "dbs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-DBS",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = DBS_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} post_timing = DBS_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_seq = post_timing{1}{8}; int n_loadinterval = post_timing{1}{7}; bool end_load = post_timing{1}{9}; int shiftlength = post_timing{1}{10}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { DBS_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,n_loadinterval,end_load,final_load,startobs,telescopetimes,loadlength,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = DBS_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBS_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_seq * (n_load + 1),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ////////////////////////////////////////////////////////////////////////// // Auxiliary procedure to compute sum of dead times across the map {int,int,int} procedure GetAllCrossSlewTimes { int[] telescopetimes = [300,180,20,0,21,0,2,10]; int scansize = 1; // Number of points measured in one scan int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles }{ // Use telescope return parameters int numpoints = telescopetimes[6]; if(scansize > 1) { // Scan return field int n_scans = numpoints / (2 * scansize * n_cycles); int sumslews = 0; int sumnods = 0; int sumreturns = 0; for(int i1 = 0 .. numpoints - 2) { int theslew = telescopetimes[i1 + 7]; if(i1 % scansize == 0) { if(i1 % (2 * scansize) == 0) { // within A-A or B-B sumreturns = sumreturns + theslew; } else { // Nod instead of slew sumnods = sumnods + theslew; } } else { sumslews = sumslews + theslew; } } // Parameters irrelevant for scansize>1 int shortmove = 0; // Main returns int tinscandead = sumnods + sumslews; int toutscandead = sumreturns; } else { // trivial computation for scansize=1; // Single point per nod int nodtime = telescopetimes[2]; // Slew time to second nod int returntime = telescopetimes[3]; // Idle time between two phases // Scan return field numpoints = telescopetimes[6]; n_scans = numpoints / scansize; sumreturns = n_scans * (n_cycles - 1) * returntime; // Initial values sumslews = 0; shortmove = returntime; // All return values for(int i2 = 0 .. numpoints - 2) { theslew = telescopetimes[i2 + 7]; sumslews = sumslews + theslew; shortmove = imin(shortmove,theslew); } tinscandead = n_scans * n_cycles * nodtime; toutscandead = sumslews + sumreturns; } return {tinscandead,toutscandead,shortmove}; } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure SScanLoadChop_noisecomputer { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference LO frequency in scan center int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz int on_inttime = 16; // Integration time per ON phase int off_inttime = 16; // Integration time per OFF phase int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ // spectral scans always use the full bandwidth for reference bool oneGHzReference = false; // Call load-chop noise computer {double,double,double,double,double} noisevalues = LoadChop_noisecomputer(band,reffreq,eff_resolution,oneGHzReference,on_inttime,off_inttime,n_cycles,tscan,tact); // Correct for multiple frequencies double multiplier = sqrt(1.0 / double(nfreq)); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; // Check for double sideband coverage if(dsb) { // Combine LSB-USB noise // In spectral scans we have only a combined noise temperature for both // sidebands, so that the USB/LSB separation is not used double[] gssb = InterpolateGssb(band,reffreq); double usbnoise_lores = noisevalues{0} / sqrt(1.0 + gssb[1] / gssb[0] * (gssb[1] / gssb[0])); double usbnoise_hires = noisevalues{1} / sqrt(1.0 + gssb[1] / gssb[0] * (gssb[1] / gssb[0])); double lsbnoise_lores = usbnoise_lores; double lsbnoise_hires = usbnoise_hires; } else { // Get single sideband noise equivalent usbnoise_lores = noisevalues{0}; usbnoise_hires = noisevalues{1}; lsbnoise_lores = noisevalues{2}; lsbnoise_hires = noisevalues{3}; } // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noisevalues{4}}; } ////////////////////////////////////////////////////////////////// // Procedure to compute detailed pre timing for the version of the // frequency switch mode without baseline measurement // {int,int,int,int,int,int,bool,int,int} procedure FSwitchNoRef_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_chop_on = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ///////////////////////////////////////////////////////////////////// CheckLOFrequencies(band,lo_freq + min(freq_throw,0.0),lo_freq + max(freq_throw,0.0)); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); CheckFswOutOfBand(band,lo_freq,freq_throw,backendreadoutparms); int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int on_inttime = 2 * n_chop_on * data_time; // compute load integration time int loadlength = duration(DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compare load interval with duration of the observation int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int n_load_on = on_inttime / load_spacing; // This determines the order of the loops if(load_spacing > 2 * on_inttime) { int n_per_on = n_chop_on; bool end_load_on = false; int on_pointing = on_inttime + jitterdead; } else { n_per_on = n_chop_on / (n_load_on + 1); if(n_per_on < 1) { SError("FS phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * (n_load_on + 1) * data_time; on_pointing = on_inttime + n_load_on * loadlength + jitterdead; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,true); } initlength = initlength + loadlength; // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {on_inttime,on_pointing,loadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling}; } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // CUS scripts dedicated to instrument configuration // and setup in AOT framework // // Main difference with ILT CUS is that input parameters // are here in the form provided by HSPOT. // // DT - 05-June-06 // VO - 10-07-2006 // DT - 18-09-2006 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ///////////////////////////// // Global procedures //Tune HIFI at frequency of interest procedure HIFITune { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; //LO frequency bool hrs1used = true; // HRS1 parameter =used bool hrs2used = true; // HRS2 parameter bool wbs1used = true; // WBS1 parameter =used bool wbs2used = true; // WBS2 parameter string target_name = "normal"; // Name of target level }{ //LO power tuning: could use either H or V polar {double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq); double x = result[0]{0}; string tuningbackend = "H"; if(iround(x) == 2) { tuningbackend = "V"; } else { tuningbackend = "H"; } LO_tuning_block_aot(band,lo_freq / 1000.0,lo_freq / 1000.0,tuningbackend,true,true,false); //Magnet tuning: could use either HRS or WBS. Not done for bands6-7 if(band != "6a" && band != "6b" && band != "7a" && band != "7b") { // Currently only the HRS is used tuningbackend = "HRS"; Magnet_tuning_block_aot(band,lo_freq / 1000.0,tuningbackend); } // //Spectrometer attenuator tuning on HBB if(wbs1used || wbs2used) { WBS_attenuators_block(band,lo_freq / 1000.0,target_name,false); } if(hrs1used || hrs2used) { HRS_tune_block_aot(band); } } {int,double,double,double,double,double} obs HifiMappingModeLoadChopOTFNoRef { string modeName = "load-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-LoadChop-OTF-NoReference",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,bool,int,int} pre_timing = OTFLoadChopNoRef_pre_timing(nlines,npoints_used,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,int} tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,bool,int,int},double,double} post_timing = OTFDoubleChopNoRef_post_timing(pre_timing,telescopetimes,nlines,data_time,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFDoubleChopNoRef_telescope(naifid,onPosition,lineDistance,nlines,line_used,scanvelocity,band,lo_freq,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{0}; bool end_load_on = post_timing{1}{4}; int n_loadinterval = post_timing{1}{2}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFLoadChopNoRef_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on,n_loadinterval,nlines * n_cycles,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,npoints_used * n_switch_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_switch_on * n_cycles,tscan,tdead); // Evaluate performance OTFDoubleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on * n_cycles,false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {int,double,double,double,double,double} obs HifiSScanModeFSwitch { string modeName = "fs-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-SScan-FSwitch",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanFSwitch_pre_timing(band,lo_freq,lo_freq_up,redundancy,freq_throw,effResolution,hr1,hr2,wb1,wb2,data_time,data_time_off,n_switch_on,n_switch_off,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double,double} post_timing = SScanDoubleChop_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,reffreq,post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int on_inttime = post_timing{1}{0}; int off_inttime = post_timing{1}{1}; int n_loadinterval = post_timing{1}{7}; int n_long_on = post_timing{1}{8}; int n_long_off = post_timing{1}{9}; int shiftlength = post_timing{1}{5}; int initlength = post_timing{1}{14}; bool final_load = post_timing{1}{12}; // efficiency parameters double avnumchop_on = post_timing{2}; double avnumchop_off = post_timing{3}; double tscan = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanFSwitch_commanding(band,reffreq,freq_throw,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,n_total,n_loadinterval,final_load,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = SScanDoubleChop_deadtimes("fs",band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,data_time_off,n_switch_on,n_switch_off,n_long_on,n_long_off,n_cycles,avnumchop_on,avnumchop_off,tscan); // // Call noise computer {double,double,double,double,double} noisevalues = SScanFSwitch_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance SScanDoubleChop_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_freq_point,n_cycles,groupnumber * n_freq_point,avnumchop_on,avnumchop_off,true,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ///////////////////////////////////////////////////////////////// // Second step of timing computation after telescope behaviour // is known - Spectral Scan frequency switch observing mode // without baseline measurement // {int,{int,int,int,int,int,int,bool,int,int},double,double} procedure SScanChopNoRef_post_timing { {int,int,int,int,int,int,bool,int,int} pre_timing = {16,16,21,1800,2,0,false,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,0]; }{ // Get all values from the pre_timing section int on_inttime = pre_timing{0}; int on_pointing = pre_timing{1}; int loadlength = pre_timing{2}; int load_spacing = pre_timing{3}; int n_per_on = pre_timing{4}; int n_load_on = pre_timing{5}; bool end_load_on = pre_timing{6}; int initlength = pre_timing{7}; int dangling = pre_timing{8}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int tend = telescopetimes[2]; // Final deceleration time // No further computations needed // Dangling readout only applies if there is no dangling load in this case if(n_load_on > 0) { dangling = 0; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute total duration int totaltime = on_pointing + dangling + tend; double tscan = double(on_inttime) / double(n_per_on * imax(n_load_on,1)); // No telescope dead time in fine pointing double tdead = 0.0; // show gyro-propagation messages // no gyro-propagation for fine_pointing GCPMessages(0,on_pointing,tend); // Return all the times needed in the observing mode modules return {totaltime,{on_inttime,on_pointing,loadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling},tscan,tdead}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure LoadChop_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval limited by the data rates int data_time_off = 4; // data dump interval on OFF int n_per_on = 2; // number of half load-sky-sky-load cycles on ON int n_per_off = 2; // number of half load-sky-sky-load cycles on OFF int n_loadinterval = 1; // number of nods before a load measurement int n_load_on = 0; // additional load measurements in ON pointing phase int n_load_off = 0; // additional load measurements in OFF pointing phase bool end_load_on = false; // Need for load after ON pointing phase bool end_load_off = false; // Need for load after OFF pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration int shiftlength = 0; // Shift of the loop start relative to the pointing }{ // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] onrates = dataparms{1}; dataparms = DataTaking(backendreadoutparms,data_time_off); double[] offrates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 7) { // The NOD-state represents our OFF position HIFIConfigureLoadChopIntegration(data_time_off,n_per_off,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load_off) { HIFILoadChopOffIntegration(data_time_off,n_per_off,band,lo_freq,offrates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureLoadChopIntegration(data_time_off,n_per_off,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFILoadChopOffIntegration(data_time_off,n_per_off,band,lo_freq,offrates); // Second phase on OFF // occurs for even cycle numbers runintostate = false; if(state[2] % 2 == 0) { if(end_load_off) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 3) { // The POINT-state represents out source position // ON integration HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i2 = 1 .. n_load_on) { HIFILoadChopOnIntegration(data_time,n_per_on,band,lo_freq,onrates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFILoadChopOnIntegration(data_time,n_per_on,band,lo_freq,onrates); // First phase in source // occurs for odd cycle numbers runintostate = false; if(state[2] % 2 == 1) { if(end_load_on) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement // (Does not occur if end_load is set) LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } // Get frequency resolution needed to measure standing wave pattern // in load-chop measurements double procedure GetLoadChopSWResolution { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("lchopswresolution",["resolution"],band,lo_freq); return dead[0]; } // Reset observation ID - closes observation block HIFICloseObs HIFI 6999 { }{ // Previous command my have used second bus slot - use NOOP to fill Hifi_HIFI_noop(); // Switch to slow housekeeping {string,int,double,double,double,double} hkparms = PeriodicHKParms("slow"); string[] pattern = QueryHKPattern(true); Hifi_HIFI_Housekeeping_on(hkparms{0},pattern[0],pattern[1],pattern[2],pattern[3],pattern[4],pattern[5]); //Fetch last obsid applicable {double,string}[] result = ConfigurationReader("name_lastobsid",["last_obsid_current"],"0",0.0); int closing_obsid = iround(result[0]{0}); //Close OBSID Hifi_HIFI_Set_OBS_ID(0,closing_obsid); // clean bus delay(1); } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure SScanFSwitch_commanding { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference characteristic LO frequency double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in both phases double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS tuning levels int data_time = 4; // chunk size int data_time_off = 4; // data dump interval on OFF int n_per_on = 1; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_per_off = 1; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_long_on = 1; // number of cycles on ON without retuning int n_long_off = 1; // number of cycles on OFF without retuning int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency int allsteps = 4; // Total number of frequency pointing periods int n_loadinterval = 1; // number of nods before a load measurement bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int shiftlength = 0; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points // First frequency double runningfreq = freqgrid[grouporder[1][0]]; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] onrates = dataparms{1}; dataparms = DataTaking(backendreadoutparms,data_time_off); double[] offrates = dataparms{1}; int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); // recompute load duration for initial load measurement int loadlength = duration(SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; bool retuneload = n_loadinterval > 1; // Tuning levels string[] targetnames = TargetNames(band,reffreq,retuning,targetlevels); string target = targetnames[0]; // All commands with a duration possibly depending on the frequency // are taken at the reference frequency to guarantee synchonization // Declare auxiliary variables to be used in the loops int i_freqcycles = 0; int i_group = 0; int i_phase = 0; // variables storing the configuration setting bool islong = false; bool isinvalid = true; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // HIFIInitObs(); TuneHIFIFsw(band,runningfreq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},target); delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 7) { // The NOD-state represents our OFF position // Reset group counter i_group = 0; runintostate = false; // long integrations not possible in last and first PS cycle if(n_cycles > 1 && state[2] % n_cycles != state[2] % 2) { if(isinvalid || !islong) { HIFIConfigureFSwitchIntegration(data_time_off,n_long_off,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFIFSwitchOffIntegration(data_time_off,n_long_off,band,reffreq,offrates); } else { if(isinvalid || islong) { HIFIConfigureFSwitchIntegration(data_time_off,n_per_off,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } // No group scanning on OFF HIFIFSwitchOffIntegration(data_time_off,n_per_off,band,reffreq,offrates); // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && state[2] % 2 == 0) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[1][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFsw(band,runningfreq,freq_throw,target); runintostate = true; } else { // final load measurement if requested if(final_load) { delay(readoutdead); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,retuneload,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 1) { isinvalid = true; if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 3) { // The POINT-state represents our source position i_phase = state[2] % 2; // ON integration runintostate = false; // long integrations not possible in last and first nod cycle if(n_cycles > 1 && state[2] % n_cycles != (state[2] % 2 + 1) % 2) { if(isinvalid || !islong) { HIFIConfigureFSwitchIntegration(data_time,n_long_on,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFIFSwitchOnIntegration(data_time,n_long_on,band,reffreq,onrates); } else { if(isinvalid || islong) { HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } HIFIFSwitchOnIntegration(data_time,n_per_on,band,reffreq,onrates); } // Other frequencies // Reset group counter i_group = 1; if(i_group <= grouplen - 1) { if(isinvalid || islong) { HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } } while(i_group <= grouplen - 1) { // retune runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen]; HIFIChangeFreqFsw(band,runningfreq,freq_throw); HIFIFSwitchOnIntegration(data_time,n_per_on,band,reffreq,onrates); i_group = i_group + 1; } // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && i_phase == 1) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[0][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFsw(band,runningfreq,freq_throw,target); runintostate = true; } else { // final load measurement if requested if(final_load) { delay(readoutdead); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,retuneload,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 0) { isinvalid = true; if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load switch delay(readoutdead); SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,retuneload,eff_resolution{0},data_time,backendreadoutparms); isinvalid = true; runintostate = false; } // Danging load - already covered above // otherwise the instrument stops halftunelength before the telescope if(state[0] == 5) { // finished shift of instrument operations relative to pointing command runintostate = false; HIFICloseObs(); } } } ////////////////////////////////////////////////////////////////////// // Generic procedure to call a Configure_spectroscopy command // for fast-chop observations {int,int} procedure FastConfigureSpectroscopy { /* Integration time */ int data_time = 10 in [4,128]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used,channel windows} }{ // Get timing parameters bool wbs_used = backendreadoutparms{2}{0} || backendreadoutparms{3}{0}; {int,int,int,int,int,int,int,int,int,int,int,int,int} timing = FastConfigureSpectroscopyParams(data_time,n_int,n_data,band,lo_freq,wbs_used); int n_wbs_start = timing{0}; int r_hrs = timing{1}; int n_wbs_integr = timing{2}; int n_hrs_integr = timing{3}; int del_hrs = timing{4}; int del_wbs = timing{5}; int t_acc_wbs = timing{6}; int t_acc_hrs = timing{7}; int n_wbs1 = timing{8}; int n_hrs_trans = timing{9}; {int,int,int,int,int[],int[],string} backendconfigure = ConfigSpectroscopyBackends(data_time / 2,backendreadoutparms); int wbs_rshift = backendconfigure{0}; int hrs_rshift = backendconfigure{1}; int hrsh_sel = backendconfigure{2}; int hrsv_sel = backendconfigure{3}; int[] wbsh_par = backendconfigure{4}; int[] wbsv_par = backendconfigure{5}; string packing = backendconfigure{6}; // Now call the command Hifi_HIFI_config_spectroscopy($BBID,n_wbs_start,r_hrs,n_wbs_integr,n_hrs_integr,del_hrs,del_wbs,t_acc_wbs,t_acc_hrs,wbsh_par[0],wbsh_par[1],wbsh_par[2],wbsh_par[3],wbsh_par[4],wbsh_par[5],wbsh_par[6],wbsh_par[7],wbsv_par[0],wbsv_par[1],wbsv_par[2],wbsv_par[3],wbsv_par[4],wbsv_par[5],wbsv_par[6],wbsv_par[7],hrs_rshift,wbs_rshift,hrsh_sel,hrsv_sel,packing); // // Return dead times and comand parameters return {n_wbs1,n_hrs_trans}; } // Change LO frequency by a small step // // Externally it has to be guaranteed that this never uses a step larger // than one index in the LO table procedure HIFIChangeFreq { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency ion MHz }{ ConfigureFPU(band,lo_freq,false); HIFITuneFreqNoretune(band,lo_freq); } {int,double,double,double,double,double} obs HifiMappingModeDBSCross { string modeName = "cross"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-DBS-Cross",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(2,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = custom_map_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSCross_post_timing(pre_timing,telescopetimes,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = custom_map_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int scansize = post_timing{1}{10}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { DBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,true); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,2,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Correct for double counting of central point // The central point noise is returned only double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; noisevalues{4} = noisevalues{4} / multiplier; // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {string,double,double}[] procedure HifiSScanModeLoadChopSequencerInit { string modeName = "load-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half load-sky-sky-load cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of LoadChop modes {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double,double,double} phaselengths = LoadChopPhaseLengths(band,lo_freq,effResolution,narrowReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // How much time for single ON phase int n_switch_on_guess = imax(iceil(2.0 * phaselengths{0} / ((double(n_freq_point_guess) + sqrt(double(n_freq_point_guess))) * 2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * sqrt(double(n_freq_point_guess)) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } // Get dead time for frequency switch double procedure GetFSwitchDeadTime { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("fs_deadtime",["duration"],band,lo_freq); return dead[0]; } // Compute the additional time needed for HK readout setting at first load int procedure HkReadoutTime { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 bool fast = false; //whether fast chop is used }{ // get time added already for normal readout if(fast) { int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); } else { readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); } // HK readout time int hkreadouttime = duration(HIFISetHK("normal",false)); int remain = imax(hkreadouttime - readoutdead,0); return remain; } // Procedure to compute all parameters needed in a Configure_spectroscopy {int,int,int,int,int,int,int,int,int,int} procedure ConfigureSpectroscopyParams { /* Integration time */ int data_time = 4; // Integration time between two data readouts int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string chopmode = "chop" in ["chop","lchop","fs","hot-cold","tp"]; // Chop mode determining the modulation dead time string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used,channel windows} }{ // Get fixed parameters from configuration and calibration files // Command jitter time is the default delay {double,string}[] result = ConfigurationReader("name_delays",["add_jitter"],band,lo_freq); int add_jitter = iround(result[0]{0}); // WBS delta time // Default total power. This should be 0. int del_wbs = add_jitter; // WBS delta time given by switch dead time if(chopmode == "chop") { double res = GetSkyChopDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "lchop") { res = GetLoadChopDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "fs") { res = GetFSwitchDeadTime(band,lo_freq); del_wbs = iceil(res * 1000.0); } if(chopmode == "hot-cold") { bool wbsused = backendreadoutparms{2}{0} || backendreadoutparms{3}{0}; res = HotColdRelaxTime(band,lo_freq,wbsused); del_wbs = iceil(res * 1000.0); } // HRS delta time - should be zero as well int del_hrs = add_jitter; // Additional delays in the readout loops - given in OBS user manual result = ConfigurationReader("name_delays",["add_hrs","add_wbs","add_jitter","wbs_init","wbs_chunksize","tacc_add","hrs_phase","min_wbs_acc","scos_jitter"],band,lo_freq); int add_hrs = iround(result[0]{0}); int add_wbs = iround(result[1]{0}); int wbs_init = iround(result[3]{0}) + iround(result[8]{0}); int wbs_chunksize = iround(result[4]{0}); int tacc_add = iround(result[5]{0}); int hrs_phase = iround(result[6]{0}); // HRS standard phase length int min_wbs_acc = iround(result[7]{0}); // WBS transfer time // Split total integration time int tint = data_time * n_data * 1000; // dead time has to be an integer multiple of the 10ms chunk time int tdead = del_wbs + add_wbs + add_jitter; int nchunk = (tdead - 1) / wbs_chunksize + 1; int tcorr = nchunk * wbs_chunksize - tdead; del_wbs = del_wbs + tcorr; tdead = tdead + tcorr; // Accumulation time // Ignores that total power can be slightly more efficient int t_acc_wbs = (tint - wbs_init) / n_data - tdead; // discretize in 10ms chunks nchunk = (t_acc_wbs - tacc_add) / wbs_chunksize; t_acc_wbs = nchunk * wbs_chunksize + tacc_add; // Check relative to minimum accumulation tim if(t_acc_wbs + del_wbs + add_wbs < min_wbs_acc + add_jitter) { SError("WBS integration too short for readout. Increase duration."); } // No WBS addition in ICU int n_wbs_integr = 1; int n_wbs_start = n_data; // HRS int hrs_fullphase = hrs_phase + del_hrs + add_hrs; int r_hrs = (t_acc_wbs + hrs_fullphase - add_jitter) / hrs_fullphase; int t_acc_hrs = (t_acc_wbs - add_jitter) / r_hrs - del_hrs - add_hrs; // for n_wbs_integr=1 identical to r_hrs int n_hrs_integr = r_hrs; // Compute actual integration time and dead time per readout // If WBS is used count only the WBS time if(backendreadoutparms{2}{0} || backendreadoutparms{3}{0}) { int tint_act = nchunk * wbs_chunksize * n_data; tdead = tdead + tacc_add; } else { tint_act = t_acc_hrs * r_hrs * n_data; tdead = tdead + r_hrs * (del_hrs + add_hrs) + add_jitter; } // Return all config_spectroscopy timing parameters return {n_wbs_start,r_hrs,n_wbs_integr,n_hrs_integr,del_hrs,del_wbs,t_acc_wbs,t_acc_hrs,tdead,tint_act}; } // Check frequency throw relative to HRS bandwidth procedure CheckFswOutOfBand { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ bool hrs1used = backendreadoutparms{0}{0}; // HRS1 to be used int hrs1resol = backendreadoutparms{0}{1}; // resolution bool hrs2used = backendreadoutparms{1}{0}; // HRS2 to be used int hrs2resol = backendreadoutparms{1}{1}; // resolution // get minimum bandwidth covered // Start from full IF double bw = GetBackendBandwidth(band,lo_freq,-1); // Both HRS if(hrs1used) { double hbw = GetBackendBandwidth(band,lo_freq,hrs1resol); bw = min(bw,hbw); } if(hrs2used) { hbw = GetBackendBandwidth(band,lo_freq,hrs2resol); bw = min(bw,hbw); } // Compare with frequency throw if(abs(freq_throw) > 0.5 * bw) { // Generate messages - first close previous paragraph message("

"); message("

Warning

"); message("

"); message("The chosen frequency throw of " + freq_throw + " MHz is large " + "compared to the HRS subband coverage. It is likely that the HRS " + "does not see some lines in both frequency-switch phases. In this " + "case, the actual S/N ratio will be lower by a factor two than the " + "predicted one."); } } // WBS attenuator tuning, block // Both polarizations are treated block WBS_tune_block_aot HIFI 6603 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band; }{ {double,string}[] result_d = ConfigurationReader("name_configwbs",["tune_target"],band,0.0); int tune_target = iround(result_d[0]{0}); //Now tune attenuators. Hifi_HIFI_Tune_WBS($BBID,tune_target); //Get delay result_d = ConfigurationReader("name_delays",["wbs_tune_delay"],band,0.0); int wbs_tune_delay = iround(result_d[0]{0}); delay(wbs_tune_delay); // } // Fast chop integration OFF-ON-OFF-ON... with telescope at OFF position block HIFIFastHalfChopOffIntegration HIFI 6054 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // readout cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int[] parms = [1,0]; // Parameters for chop cycles double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_fast_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3","chop_M3right"],parms,rates); } // Procedure to get timing in a spectroscopy measurement {double,double} procedure GetInstDeadFastChop { /* Integration time */ int data_time = 10 in [4,128]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 2; // Integration time counter /* Parameters determining the delays - used in calibration reader */ string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency /* Backend settings */ {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used,channel windows} }{ // Get timing parameters bool wbs_used = backendreadoutparms{2}{0} || backendreadoutparms{3}{0}; {int,int,int,int,int,int,int,int,int,int,int,int,int} timing = FastConfigureSpectroscopyParams(data_time,n_int,n_data,band,lo_freq,wbs_used); int tdead_chop = timing{10}; int tdead_data = timing{11}; int tint = timing{12}; // For the noise computation there is no difference between initial dead // and readout dead, they are all summed up // Return dead time per full integration double tintall = double(tint) / 1000.0; double tdeadphase = double(tdead_chop) / 1000.0; return {tintall,tdeadphase}; } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode // // The sum of drift noise and radiometric noise is computed. {double,double,double,double,double} procedure DBS_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuum = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles double tscan = 60.0; // Total average duration of one scan {double,double,double} tact = {10.0,4.9,0.05}; // Field of actual dead and integration times }{ double tdead = tact{0}; // Average total dead time in one scan double inttimeperphase = tact{1}; // Actual integration time double deadtimeperphase = tact{2}; // Dead time per switch phase // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise if(continuum) { double[] allanparms = InterpolateTpAllan(band,lo_freq,oneGHzReference); } else { allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); } // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Differential Allan variance if(continuum) { allanparms = InterpolateTpChopAllan(band,lo_freq,oneGHzReference); } else { allanparms = InterpolateSpecChopAllan(band,lo_freq,oneGHzReference); } // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double dallan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Compute the relative noise for the detailed timing double deadtimeperswitch = deadtimeperphase; double inttime = (tscan - tdead) / 2.0; // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = DoubleDifferenceNoise(inttimeperphase / allan_time_lores,[1.0,1.0,inttime / allan_time_lores,inttime / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); double systemnoise_hires = DoubleDifferenceNoise(inttimeperphase / allan_time_hires,[1.0,1.0,inttime / allan_time_hires,inttime / allan_time_hires,deadtimeperswitch / allan_time_hires,tdead / allan_time_hires,alpha,dallan_time_hires / allan_time_hires,dalpha]); double noiseratio = DoubleDifferenceNoiseRatio(inttimeperphase / allan_time_lores,[1.0,1.0,inttime / allan_time_lores,inttime / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); // Compute total double sideband noise // Correct for signal in difference phase double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 4000000.0 * double(n_cycles) * tscan)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 4000000.0 * double(n_cycles) * tscan)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } //Set LOU to nominal, block //Set LOU in nominal mode with no channel selected block Set_LO_Nominal_block_aot HIFI 6626 { }{ {double,string}[] result = ConfigurationReader("name_delays",["set_to_nominal_delay"],"0",0.0); int set_to_nominal_delay = iround(result[0]{0}); // Hifi_HIFI_HL_Normal($BBID); delay(set_to_nominal_delay); // } // Procedure used by the mapping sequencer to compute the // OFF integration time int procedure SpotOTFOffTime { /* Basic setup */ string band = "4a"; double fe_lof_0 = 978.2; /* Map parameters */ double flyX = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; /* Other sequence parameters */ int n_int_on = 1; int n_linesperscan = 1; }{ // start Volkers list double lo_freq = 978200.0; // Lower LO frequency limit in MHz int nlines = 1; double stepsize = 0.0; int npoints = 1; // general definitions double factorMHzPerGHz = 1000.0; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; // start translation lo_freq = fe_lof_0 * factorMHzPerGHz; // Map size stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,lo_freq); stepsize = s[0]; } npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); // derive OFF integration time double n_pointsperscan = double(n_linesperscan * npoints); int n_switch_off = iceil(double(n_int_on) * 0.67 * sqrt(n_pointsperscan)); return n_switch_off; } {string,double,double}[] procedure HifiPointModeFSwitchNoRefSequencerInit { string modeName = "fs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // inherit from load-chop mode {string,double,double}[] retvalues = HifiPointProcLoadChopNoRefSequencerInit(naifid,ra,dec,band,lo_freq,effResolution,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); return retvalues; } ///////////////////////////////////////////////////////////////// // New routine to select the reference frequency as the median // of the three relevant points with respect to Tsys double procedure ComputeReferenceFreq { string band = "4a"; // HIFI band double lo_freq1 = 978200.0 in [480000.0,1950000.0]; // LO frequency double lo_freq2 = 979600.0 in [480000.0,1950000.0]; // LO frequency }{ // standard guess - center of the interval double reffreq = 0.5 * (lo_freq1 + lo_freq2); double t1 = InterpolateTsys(band,reffreq); double t2 = InterpolateTsys(band,lo_freq1); double t3 = InterpolateTsys(band,lo_freq2); // first check for exclusion of really bad values double excludelimit = 1.414; // sqrt(2) factor double bestt = min(min(t1,t2),t3); excludelimit = excludelimit * bestt; bool twoexcluded = false; // go through the three possible combinations if(t1 > excludelimit && t2 > excludelimit) { reffreq = lo_freq2; twoexcluded = true; } if(t1 > excludelimit && t3 > excludelimit) { reffreq = lo_freq1; twoexcluded = true; } if(t2 > excludelimit && t3 > excludelimit) { twoexcluded = true; } // Treatment for at least two valid points - use median if(!twoexcluded) { // go through the possible combinations if(t1 > t2 && t2 >= t3 || t1 < t2 && t2 <= t3) { reffreq = lo_freq1; } if(t1 > t3 && t3 > t2 || t1 < t3 && t3 < t2) { reffreq = lo_freq2; } } return reffreq; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure DBSRaster_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int nlines = 20; // Number of lines in the map int npoints = 20; // Number of points in the map int n_cycles = 1; // Number of nodding cycles int n_chop = 1; // number of chop cycles {double,double,double} tact = {10.0,4.9,0.05}; // Field of actual dead and integration times }{ double inttimeperphase = tact{1}; // Actual integration time in ON phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for map coverage idealnoise = idealnoise * double(npoints * nlines); double efficiency = idealnoise / obsnoise; // Compute the actual integration time double posinttime = double(npoints * nlines * n_cycles * 2 * n_chop) * inttimeperphase; // Check total integration time double timeefficiency = 2.0 * posinttime / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // Non-standard messages message("

"); message("The observed map consists of " + nlines + " lines with " + npoints + " points in each line.
"); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posinttime,timeefficiency,efficiency,relnoise,false); } // Load calibration measurement procedure LoadMeasurement_FCal { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency double deltanu = 1.0; // minimum effective resolution of the calibrated data int data_time = 4; // time between subsequent data readouts {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Initial computations {int,int,bool} calinit = HIFICalInit(band,lo_freq,deltanu,data_time); int used_datatime = calinit{0}; int n_inttime = calinit{1}; bool retuning = calinit{2}; // Perform zero and comb measurement ZeroCombMeasurement_FCal(band,lo_freq,used_datatime,backendreadoutparms); // No we perform the actual hot-cold measurement // slow_chop_spectroscopy int danglingreadout = HIFI_Calibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,retuning); // Retune and another load if we are in HEB bands if(retuning) { // we have to wait for readout delay(danglingreadout); // Another LO vector scan at the same frequency for a stable HEB operation HIFITuneFreq(band,lo_freq,false,""); danglingreadout = HIFI_Calibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,false); } } ///////////////////////////////////////////////////////////////// // Spectral scan in DBS observing modes // {string,double,double}[] procedure HifiSScanProcDBSSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of DBS modes {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // Get the drift parameters to compute the drift noise // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double} phaselengths = DBSPhaseLengths(band,reffreq,effResolution,continuumDetection,narrowReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // remaining part for n_switch int n_switch_on_guess = iceil(phaselengths{0}) / (n_freq_point_guess * 2 * data_time_guess) + 1; int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } // Fast chop integration OFF-ON-OFF-ON... with telescope at ON position block HIFIFastHalfChopOnIntegration HIFI 6053 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // readout cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int[] parms = [1,0]; // Parameters for chop cycles double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_fast_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3","chop_M3right"],parms,rates); } //////////////////////////////////// // Test mode - Load chop mode without baseline calibration // {int,double,double,double,double,double} obs HifiPointProcLoadChopNoRef_FCal { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-LoadChop-NoReference",{data_time,0,0,0,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,bool,int,int} pre_timing_f = LoadChopNoRef_FCal_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,pre_timing_f); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing_f = SingleChopNoRef_post_timing(pre_timing_f,telescopetimes); // Now the actual observation starts // Prepare telescope command tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,post_timing_f{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Consistency check int totaltime = post_timing_f{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// // standard parameters for fine pointing int loadlength = post_timing_f{1}{2}; int n_per_on = post_timing_f{1}{4}; int n_load_on = post_timing_f{1}{5}; bool end_load_on = post_timing_f{1}{6}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { LoadChopNoRef_FCal_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on,n_load_on,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // There are no telescope dead times involved in this mode {double,double,double} tact = SingleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_per_on * (n_load_on + 1),tscan,tdead); // Evaluate performance SingleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_per_on * (n_load_on + 1),false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {string,double,double}[] procedure HifiMappingModeOTFSequencerInit { string modeName = "fly"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,5]; // chunk size given by the data rates and optimum speed int n_int_on = 1 in [1,1800]; // Supersamplingfactor int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int main_phase = iceil(0.3 * allan_time_lores); // How many lines could we do at most using datalimit? int n_linesperscan_guess = main_phase / datalimit + 1; n_linesperscan_guess = imax(n_linesperscan_guess * n_linesperscan_guess / npoints,1); // restrict the scan size if(nlines == 1 && n_linesperscan_guess > 1) { n_linesperscan_guess = 2; } else { n_linesperscan_guess = IMultiple(n_linesperscan_guess,nlines); n_linesperscan_guess = imin(n_linesperscan_guess,nlines); } int n_linesperscan_range = 1 - n_linesperscan_guess; if(n_linesperscan_range == 0) { n_linesperscan_range = 1; } double n_pointsperscan = double(n_linesperscan * npoints); // Compute back int int_time_guess = imax(main_phase / iceil(sqrt(n_pointsperscan)),datalimit); int data_time_guess = imin(5,int_time_guess); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_int_on_guess = imax(int_time_guess / data_time_guess,1); int n_int_on_range = 1 - n_int_on_guess; if(n_int_on_range == 0) { n_int_on_range = 1; } // OFF integration int n_switch_off_guess = ifloor(double(n_int_on) * 0.67 * sqrt(n_pointsperscan)); int n_switch_off_range = n_switch_off_guess / 3; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_linesperscan",double(n_linesperscan_guess),double(n_linesperscan_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)}]; return retvalues; } //Systematic deflux at beginning of each band switch procedure Deflux_SingleBand_proc_aot { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; // LO frequency in GHz }{ //Do deflux block only for bands 1 to 4 if(band == "1a" || band == "1b" || band == "2a" || band == "2b" || band == "3a" || band == "3b" || band == "4a" || band == "4b") { //First magnet tuning Magnet_tuning_block_aot(band,lo_freq,"HRS"); //Deflux heaters Heater_block_aot(band); //Second magnet tuning Magnet_tuning_block_aot(band,lo_freq,"HRS"); } } //////////////////////////////////// // Auxiliary function to compute the noise of an ideal instrument with // 100% observing efficiency for comparison {int,double,double,double,double,double} procedure IdealInstrument { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz int totaltime = 8; // Total integration time }{ // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); double phasetime = double(totaltime); double noiseratio = 0.0; // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(1.0 / (eff_resolution{1} * 1000000.0 * phasetime)); double dsbnoise_hires = tsys * sqrt(1.0 / (eff_resolution{0} * 1000000.0 * phasetime)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // return total time with initial slew int returntime = totaltime; // Originally I had added 180s from telescope // Return noise values and the maximum ratio of drift to radiometric noise return {returntime,usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } ///////////////////////////////////////////////////////////////// // Get valid table range {int,int} procedure GetFScanBoundaries { string band = "4a"; // HIFI band double freq_throw = -40.0; // throw of frequency switch in MHz }{ // read master file string calibfile = slookup("frequencystep_masterfile",band,"tablefile"); double[] allfpoints = dcolumn(calibfile,"stepfrequency"); // get table size int iindex1 = length(allfpoints); if(freq_throw < 0.0) { int istart = 1; int iend = iindex1 - 2; double goallo = allfpoints[1] - freq_throw; while(allfpoints[istart] < goallo) { istart = istart + 1; } } else { istart = 1; iend = iindex1 - 2; goallo = allfpoints[iindex1 - 2] - freq_throw; while(allfpoints[iend] > goallo) { iend = iend - 1; } } return {istart,iend}; } ///////////////////////////////////////////////////////////////// // Procedure to derive the backend settings for the peakup {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} procedure PeakupBackendSettings { string backend = "WBS" in ["WBS","HRS"]; // backend to use - resolution string polarization = "H" in ["H","V"]; // backend to use - polarization string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int redundancy = 4; // Equivalent frequency scan redundancy }{ // First get the backend configuration bool isWbs = backend == "WBS"; bool isH = polarization == "H"; // Settings for unused spectrometers int[][] emptyWbsWindows = [[0,0],[0,0],[0,0],[0,0]]; {bool,int,double[],bool[]} unusedHrs = {false,1,[-110.0,110.0,0.0,0.0],[false,false,false,false]}; // Standard configuration of the backends if(isWbs) { // Get normal WBS windows double[] x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,lo_freq); int[][] stdWbsWindows = [[iround(x[0]),iround(x[1])],[iround(x[2]),iround(x[3])],[iround(x[4]),iround(x[5])],[iround(x[6]),iround(x[7])]]; // Assign to polarizations if(isH) { {bool,int[][]} wbs1 = {true,stdWbsWindows}; {bool,int[][]} wbs2 = {false,emptyWbsWindows}; {bool,int,double[],bool[]} hrs1 = unusedHrs; {bool,int,double[],bool[]} hrs2 = unusedHrs; } else { wbs1 = {false,emptyWbsWindows}; wbs2 = {true,stdWbsWindows}; hrs1 = unusedHrs; hrs2 = unusedHrs; } } else { // Get fixed HRS parameters {{bool,int,double[],bool[]},{bool,int,double[],bool[]}} hrsparms = GetSpectralScanHRS(redundancy,band); if(isH) { hrs1 = hrsparms{0}; hrs2 = unusedHrs; wbs1 = {false,emptyWbsWindows}; wbs2 = {false,emptyWbsWindows}; } else { hrs1 = unusedHrs; hrs2 = hrsparms{1}; wbs1 = {false,emptyWbsWindows}; wbs2 = {false,emptyWbsWindows}; } } return {hrs1,hrs2,wbs1,wbs2}; } ///////////////////////////////////////////////////////////////// // Spectral scan in frequency switch without OFF calibration // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiSScanProcFSwitchNoRef { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-SScan-FSwitch-NoReference",{data_time,0,0,0,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanFSwitchNoRef_pre_timing(band,lo_freq,lo_freq_up,redundancy,freq_throw,effResolution,hr1,hr2,wb1,wb2,data_time,n_cycles,n_freq_point,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar = Fine_telescope(naifid,onPosition,band,reffreq,pre_timing{0}); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing = SScanChopNoRef_post_timing(pre_timing{0},telescopetimes); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = Fine_telescope(naifid,onPosition,band,reffreq,post_timing{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int loadlength = post_timing{1}{2}; int n_per_on = post_timing{1}{4}; int n_load_on = post_timing{1}{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanFSwitchNoRef_commanding(band,reffreq,freq_throw,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_per_on,n_load_on,groupnumber,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,reffreq,hr1,hr2,wb1,wb2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = SScanChopNoRef_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,n_per_on * imax(n_load_on,1),true,tscan,tdead); // Evaluate performance SScanChopNoRef_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_per_on * imax(n_load_on,1),groupnumber * n_freq_point,true,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Fast chop integration OFF-ON-OFF-ON... with telescope at OFF position block HIFIFastChopOffIntegration HIFI 6043 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // readout cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int[] parms = [1,0]; // Parameters for chop cycles double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_fast_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3left","chop_M3right"],parms,rates); } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the composite position telescope command for the // observing mode {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} procedure PositionSwitch_telescope { int naifid = 0; // Tracking object ID {double,double} onposition = {0.0,0.0}; // Coordinates of the source {double,double} offposition = {0.2,0.2}; // Coordinates of the OFF position string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} timing = {16,16,16,16,21,11,1800,32,2,2,0,0,false,false,50,0}; int n_cycles = 2; // Number of half OFF-ON-ON-OFF cycles }{ // Assign values int on_pointing = timing{2}; // Pointing on on-position int off_pointing = timing{3}; // Pointing OFF on-position int loadlength = timing{4}; // Load duration int n_loadinterval = timing{7}; // Number of nods between load measurements int initlength = timing{14}; // Initial setup time int dangling = timing{15}; // Final load measurement // Create variables for telescope command string ib = GetBoresight(band,lo_freq,false); // A change of ra-dec depending on naifid may be needed double ra = onposition{0}; double dec = onposition{1}; // Compute offset: This is always in sky coordinates {double,double} offset = AngularOffset(onposition,offposition); double patt = AngleFromVector(offset); double slewlength = AngleVectorLength(offset); slewlength = max(slewlength * 3600.0,2.0); // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(on_pointing < 10) { SError("Source pointing phase length too short. Increase the number of integrations."); } if(off_pointing < 10) { SError("OFF pointing phase length too short. Increase the number of integrations."); } if(slewlength > 7200.0) { IError("Slew distance too long. Choose a closer OFF position."); } // repetition at multiple frequencies not yet implemented: int thold = 0; int nhold = 0; int n_repeat = n_cycles; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,true,patt,0.0,0.0,n_repeat,slewlength,on_pointing,off_pointing,loadlength,n_loadinterval,thold,nhold}; } // Drift noise from a symmetric two-phase observation // This is still to be scaled by a factor 1.0/(B_fluct*T_Allan) double procedure TwoPhaseDrift { double x = 0.1; // integration time relative to Allan time double d = 0.3; // delay relative to Allan time double alpha = 2.5; // drift exponent }{ if(x >= 0.0) { double a1 = alpha + 1.0; double y = (pow(2.0 * x + d,a1) - 2.0 * pow(x + d,a1) + pow(d,a1) - 2.0 * pow(x,a1)) / ((pow(2.0,alpha) - 2.0) * x * x); } else { // forbid x values <=0 y = 1.0E11 * (1.0 - x); } return y; } // Drift noise from an asymmetric two-phase observation // This is still to be scaled by a factor 1.0/(B_fluct_A*T_Allan) double procedure AsymmetricDrift { double xa = 0.1; // integration time in phase A relative to Allan time double xb = 0.1; // integration time in phase B relative to Allan time double d = 0.3; // delay relative to Allan time double alpha = 2.5; // drift exponent }{ if(xa >= 0.0) { double a1 = alpha + 1.0; double y = ((pow(xa + xb + d,a1) - pow(xa + d,a1) - pow(xb + d,a1) + pow(d,a1)) / (xa * xb) - pow(xa,a1) / (xa * xa) - pow(xb,a1) / (xb * xb)) / (pow(2.0,alpha) - 2.0); } else { // forbid x values <=0 y = 1.0E11 * (1.0 - xa); } return y; } ///////////////////////////////////////////////////////////////// // Procedure to simulate a spectral scan frequency change using // HSPOT parameters needed by the sequencer // procedure SScanRetuning { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double fe_lof_0 = 978.2; //LO frequency in normal modes double lo_freq1 = 978.2; //LO frequency in spectral scans }{ double lo_freq = 978.2; // LO frequency in MHz if(lo_freq == lo_freq1) { lo_freq = fe_lof_0 * 1000.0; } else { lo_freq = lo_freq1 * 1000.0; } HIFIRetuneFreq(band,lo_freq,""); } /////////////////////////////////////////////////////// // Generic procedures to tune S/S in HIFI // Set magnet currents for both polarizations, procedure procedure Set_Magnet_current_proc_fm { double mag_curr_h = 1.0; //Magnet current H polarization double mag_curr_v = 1.0; //Magnet current V polarization }{ Hifi_HIFI_CH1_MX_MG_C($BBID,mag_curr_h); Hifi_HIFI_CV1_MX_MG_C($BBID,mag_curr_v); delay(1); } ////////////////////////////////////////////////////////////////////////// // Auxiliary procedure to compute sum of dead times across the map {int,int} procedure Raster_slewtimes { /* Map setup */ int nlines_tot = 1; // Number of rows in the map int npoints = 10; // Number of points per row int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles int scansize = 1; // Number of points measured in one scan /* Telescope dead times */ int nodtime = 20; // Slew time to second nod int slewtime = 10; // Slew time to next point int slewline = 10; // Slew between lines int returntime = 2; // Idle time between two phases }{ /////////////////////// // Long computation for scansize > 1 to obtain all slew durations // create field of slews in the maps for simple counting if(scansize > 1) { // Create array containing all slews int[] inslews = []; int slewcount = -1; for(int icycl = 0 .. n_cycles - 1) { for(int iline = 0 .. nlines_tot - 1) { for(int ipoints = 0 .. npoints - 1) { slewcount = slewcount + 1; inslews[slewcount] = slewtime; } inslews[slewcount] = slewline; } inslews[slewcount] = returntime; } inslews[slewcount] = 0; // Count all slews using the array produced above int tinscandead = 0; int toutscandead = 0; // map point counter int slew1 = 0; int slew2 = 0; bool inmap1 = true; // k-2k-2k .. phase indicator bool aphase1 = false; bool aphase2 = true; while(slew1 <= slewcount || slew2 <= slewcount) { // A pointing phase if(inmap1) { slew1 = slew1 + 1; if(slew1 % scansize == 0) { aphase1 = !aphase1; if(aphase1) { tinscandead = tinscandead + nodtime; inmap1 = !inmap1; } else { toutscandead = toutscandead + inslews[slew1 - 1]; } } else { tinscandead = tinscandead + inslews[slew1 - 1]; } } else { // B pointing phase slew2 = slew2 + 1; if(slew2 % scansize == 0) { aphase2 = !aphase2; if(aphase2) { tinscandead = tinscandead + nodtime; inmap1 = !inmap1; } else { toutscandead = toutscandead + inslews[slew2 - 1]; } } else { tinscandead = tinscandead + inslews[slew2 - 1]; } } } } else { // Single point per nod int n_scans = nlines_tot * npoints / scansize; tinscandead = n_scans * n_cycles * nodtime; toutscandead = nlines_tot * (npoints - 1) * slewtime + (nlines_tot - 1) * slewline + n_scans * (n_cycles - 1) * returntime; } return {tinscandead,toutscandead}; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF observing mode {int,int,int,int,int,int,int,int} procedure OTFLoadChop_pre_timing { int nlines_tot = 1; // Number of rows in the map int npoints = 10; // Number of data dumps per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); // Is the map size an integer multiple of the scan size? CheckReasonableLineNumber(nlines_tot,true); if(nlines_tot == 1) { int n_scans = 1; } else { if(nlines_tot % n_linesperscan != 0) { SError("Map size is no integer multiple of the scan size."); } n_scans = nlines_tot / n_linesperscan; } // Compute parameters for the instrument timing int n_pp = 2 * npoints * n_switch_on; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compute parameters for the pointing command int jitterdead = GetMaxTimeJitter(band,lo_freq); int off_inttime = 2 * data_time_off * n_switch_off; // OFF integration time int off_pointing = off_inttime + jitterdead; // increase by commanding jitter // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // First estimate of the load interval int scan_time = n_linesperscan * n_pp * data_time + off_pointing; if(scan_time > load_interval) { IError("Scan duration too long for required load period. " + "Reduce the map size or increase the step size."); } int n_loadinterval = imax(load_interval / scan_time,1); n_loadinterval = imin(n_loadinterval,32); // Make sure that load slews occur at the same position in each coverage n_loadinterval = IMultiple(n_loadinterval,n_scans); // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed in the observing mode modules return {n_pp,n_scans,off_inttime,off_pointing,loadlength,n_loadinterval,initlength,dangling}; } //Get blue min double procedure Get_BLUE_MIN_D2_proc_fm { string band = "4a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO Frequency }{ //Remove this when SCR2220 implemented string name_confindex = "name_confindex_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_confindex = "name_confindex_b"; } {double,string}[] result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq); int freq_nx = ifloor(result[0]{0}); //Fetch D2 blue min and max result = ConfigurationReader("name_configlcublue",["blmn1a","blmx1a","blmn1b","blmx1b","blmn2a","blmx2a","blmn2b","blmx2b","blmn3a","blmx3a","blmn3b","blmx3b","blmn4a","blmx4a","blmn4b","blmx4b","blmn5a","blmx5a","blmn5b","blmx5b","blmn6a","blmx6a","blmn6b","blmx6b","blmn7a","blmx7a","blmn7b","blmx7b"],band,double(freq_nx)); // //Anticipated implementation of SCR-2220: not yet active until we get the first set of files string name_configlcu = "name_configlcu_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlcu = "name_configlcu_b"; } //{double, string}[] result = ConfigurationReader(name_configlcu, // ["drain2_v_blmn","drain2_v_blmx"],band, lo_freq); double drain2_min = 0.0; if(band == "1a") { drain2_min = result[0]{0}; } if(band == "1b") { drain2_min = result[2]{0}; //result[0]{0}; } if(band == "2a") { drain2_min = result[4]{0}; //result[0]{0}; } if(band == "2b") { drain2_min = result[6]{0}; //result[0]{0}; } if(band == "3a") { drain2_min = result[8]{0}; //result[0]{0}; } if(band == "3b") { drain2_min = result[10]{0}; //result[0]{0}; } if(band == "4a") { drain2_min = result[12]{0}; //result[0]{0}; } if(band == "4b") { drain2_min = result[14]{0}; //result[0]{0}; } if(band == "5a") { drain2_min = result[16]{0}; //result[0]{0}; } if(band == "5b") { drain2_min = result[18]{0}; //result[0]{0}; } if(band == "6a") { drain2_min = result[20]{0}; //result[0]{0}; } if(band == "6b") { drain2_min = result[22]{0}; //result[0]{0}; } if(band == "7a") { drain2_min = result[24]{0}; //result[0]{0}; } if(band == "7b") { drain2_min = result[26]{0}; //result[0]{0}; } return drain2_min; } {int,double,double,double,double,double} obs HifiMappingModeFastDBSRaster { string modeName = "raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-FastChop-DBS-Raster",{data_time,0,n_switch_on,n_int_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(nlines,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastDBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Put system into pumped mixing state, i.e. init FPU and LO tuning procedure Init_Mixing_proc_aot { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; // LO frequency in GHz }{ // At that stage we should just have switched on the LO sync(); int startobs = time(); // FPU setting at this frequency Init_MSA_aot(band,"CLOSE",lo_freq,true,"ON"); // How long do we have to wait between LO switch-on and first tuning ? // The Init_MSA time is included in the delay double[] tunewait = CalibrationReader("tunetime",["lowarmup"],band,lo_freq * 1000.0); int rest = iceil(tunewait[0]) - (time() - startobs); delay(rest); // //LO power tuning: could use either H or V polar {double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq); double x = result[0]{0}; string tuningbackend = "H"; if(iround(x) == 2) { tuningbackend = "V"; } else { tuningbackend = "H"; } // Actually perform LO tuning LO_tuning_block_aot(band,lo_freq,lo_freq,tuningbackend,true,true,false); } //////////////////////////////////// // Fast chop DBS raster - cross observing mode // {string,double,double}[] procedure HifiMappingProcFastDBSCrossSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the two raster lines int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power levels bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // inherit from dbs-raster mode {string,double,double}[] retvalues = HifiMappingProcFastDBSRasterSequencerInit(naifid,ra,dec,{0.0,double(npoints / 2) * stepsize},2,stepsize,npoints,band,lo_freq,effResolution,continuumDetection,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); return retvalues; } ///////////////////////////////////////////////////////////////// // Procedure to compute the WBS IF levels for spectral scans {bool,double[]} procedure TargetLevels { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency double[][] retunegrid = [[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]]; // dB grid }{ // Get target limits double[] limits = CalibrationReader("attenuator_levels",["sscan_max","sscan_min"],band,lo_freq); // Parameters of the field int nfreq = length(retunegrid); int nsub = length(retunegrid[0]); // Go through subbands - find maximum double[] maxfield = []; for(int i = 0 .. nsub - 1) { maxfield[i] = retunegrid[0][i]; for(int j = 1 .. nfreq - 1) { maxfield[i] = max(retunegrid[j][i],maxfield[i]); } } // Renormalize for(int ii = 0 .. nsub - 1) { double norm = limits[0] / maxfield[ii]; for(int jr = 0 .. nfreq - 1) { retunegrid[jr][ii] = norm * retunegrid[jr][ii]; } } // search for minimum - use for target level double[] targetlevels = []; for(int jj = 0 .. nfreq - 1) { targetlevels[jj] = arraymin(retunegrid[jj]); } double absmin = arraymin(targetlevels); // Check for retuning needs bool retuning = absmin < limits[1]; if(retuning) { message("Wide spectral range requires repeated backend tunings.
"); } return {retuning,targetlevels}; } //////////////////////////////////// // Special DBS raster - cross observing mode // {string,double,double}[] procedure HifiMappingProcDBSCrossSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the two raster lines int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // inherit from dbs-raster mode {string,double,double}[] retvalues = HifiMappingProcDBSRasterSequencerInit(naifid,ra,dec,{0.0,double(npoints / 2) * stepsize},2,stepsize,npoints,band,lo_freq,effResolution,continuumDetection,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); return retvalues; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure FSwitch_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval limited by the data rates int data_time_off = 4; // data dump interval on OFF int n_per_on = 1; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_per_off = 1; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_loadinterval = 1; // number of nods before a load measurement int n_load_on = 0; // additional load measurements in ON pointing phase int n_load_off = 0; // additional load measurements in OFF pointing phase bool end_load_on = false; // Need for load after ON pointing phase bool end_load_off = false; // Need for load after OFF pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int loadlength = 50; // Load duration int shiftlength = 0; // Shift of the loop start relative to the pointing }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] onrates = dataparms{1}; dataparms = DataTaking(backendreadoutparms,data_time_off); double[] offrates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 7) { // The NOD-state represents our OFF position HIFIConfigureFSwitchIntegration(data_time_off,n_per_off,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load_off) { HIFIFSwitchOffIntegration(data_time_off,n_per_off,band,lo_freq,offrates); // Perform load calibration delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureFSwitchIntegration(data_time_off,n_per_off,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFSwitchOffIntegration(data_time_off,n_per_off,band,lo_freq,offrates); // Second phase on OFF // occurs for even cycle numbers runintostate = false; if(state[2] % 2 == 0) { if(end_load_off) { delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 3) { // The POINT-state represents our source position HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); // ON integration // Loop for load cycles for(int i2 = 1 .. n_load_on) { HIFIFSwitchOnIntegration(data_time,n_per_on,band,lo_freq,onrates); // Perform load calibration delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFSwitchOnIntegration(data_time,n_per_on,band,lo_freq,onrates); // First phase in source // occurs for odd cycle numbers runintostate = false; if(state[2] % 2 == 1) { if(end_load_on) { delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load nod delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement // ( Does not occur if end_load is set) DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure OTFDoubleChopNoRef_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int nlines = 20; // Number of lines in the map int npoints = 20; // Number of points in the map int n_cycles = 1; // Number of map coverages bool fs = false; // whether frequency switch used double tscan = 10.0; // Total average duration of one scan double tdead = 0.05; // Average dead time in one chop cycle }{ // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for map coverage idealnoise = idealnoise * double(npoints * nlines); double efficiency = idealnoise / obsnoise; // Compute the actual integration time double posinttime = double(n_cycles * nlines * npoints) * (tscan - tdead); double posofftime = 0.0; int instrumenttime = iceil(double(n_cycles * nlines * npoints) * tscan); // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // Non-standard messages message("

"); message("The observed map consists of " + nlines + " OTF lines, each covering " + npoints + " readout points.
"); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,fs); } // active HK while instrument is not integrating block HIFIActiveHK HIFI 6002 { string speed = "normal" in ["fast","normal","slow"]; // Select HK rate int period = 10; // Time for which active HK is to be used }{ // Compute active period int aperiod = period - 4; // Get parameters {string,int,double,double,double,double} hkparms = PeriodicHKParms(speed); // ignored if time is too short if(aperiod > hkparms{1}) { // initial delay delay(2); // Correct for additional readouts double numreadout = double(aperiod / hkparms{1}); double enhance = (1.0 + numreadout) / numreadout; // Active HK string[] pattern = QueryHKPattern(true); non_ess_hk_data_rate(enhance * hkparms{3} / 1024.0); ess_hk_data_rate(enhance * hkparms{5} / 1024.0); Hifi_HIFI_Housekeeping_on(hkparms{0},pattern[0],pattern[1],pattern[2],pattern[3],pattern[4],pattern[5]); delay(aperiod); // Back to passive HK pattern = QueryHKPattern(false); non_ess_hk_data_rate(hkparms{3} / 1024.0); ess_hk_data_rate(hkparms{5} / 1024.0); Hifi_HIFI_Housekeeping_on(hkparms{0},pattern[0],pattern[1],pattern[2],pattern[3],pattern[4],pattern[5]); delay(2); } else { delay(period); } } //Procedure computing the maximum time for LO configuration // over a given SScan range relative to the time at a reference frequency // int procedure ComputeLOTimeDifference { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz double reffreq = 978200.0; // Reference frequency }{ // Translate MHz from AOT API to configuration table in GHz double lofreq_ref = reffreq / 1000.0; double lofreq_min = lo_freq / 1000.0; double lofreq_max = lo_freq_up / 1000.0; //Some sanity checks if(lofreq_min >= lofreq_max) { error("Min LO frequency for SScan is higher than max one"); } //Get safe Vd2 value for this LO subband double[] cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lofreq_ref); double drain2_safe = cresult[0]; //Get tuning delays {double,string}[] result = ConfigurationReader("name_delays",["lock_lo_delay","vd2_rampup_speed"],band,lofreq_ref); double lock_lo_delay = result[0]{0}; double vd2_rampup_speed = result[1]{0}; // Reference value double tune_range_factor = 1.05; string name_configlcutune = "name_configlcutune_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlcutune = "name_configlcutune_b"; } result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lofreq_ref); int ref_delay = iceil(lock_lo_delay + (result[0]{0} * tune_range_factor - drain2_safe) / vd2_rampup_speed); //Readout content of LCU Vd2 table only once out of loop string tab = "configlcu" + band + "tune.config"; double[] allVd2 = dcolumn(tab,"drain2_v"); //Determine bracketting indices int index_min = ibracket(tab,"index",lofreq_min); int index_max = ibracket(tab,"index",lofreq_max); //Loop on all bracketted indices double max_vd2 = 0.0; for(int i = index_min .. index_max) { max_vd2 = max(allVd2[i],max_vd2); } // Maximum value int delay_max = iceil(lock_lo_delay + (max_vd2 * tune_range_factor - drain2_safe) / vd2_rampup_speed); // Return difference by which the duration has to be corrected return delay_max - ref_delay; } // Get actual frequency throw best suited for the LO band double procedure GetTrueFsThrow { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency string throwstring = "small-negative"; // Frequency throw identifier }{ // perform lookup double[] throw = CalibrationReader("fsthrows",[throwstring],band,lo_freq); return throw[0]; } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for a // Spectral Scan Load-Chop observing mode // // We assume that each telescope motion is related to an // instrument calibration. // {{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} procedure SScanLoadChop_pre_timing { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_chop_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_chop_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Create composite readout structure for backends {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get frequency grid characteristic parameters {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq_low,lo_freq_up,redundancy,0.0,n_freq_point); double reffreq = fqparms{1}; double[] freqgrid = fqparms{2}; int[][] grouporder = fqparms{3}; // Process tuning level grid double[][] levelgrid = GetSScanLevelGrid(band,wbs1,wbs2,freqgrid,fqparms{0},grouporder); {bool,double[]} targets = TargetLevels(band,reffreq,levelgrid); bool retuning = targets{0}; double[] targetgrid = targets{1}; string reftarget = ""; if(retuning) { reftarget = "sscan_normal"; } {int,double,double[],int[][],bool,double[],int,bool} spectralparms = {fqparms{0},reffreq,freqgrid,grouporder,retuning,targetgrid,fqparms{4},fqparms{5}}; ////////////////////////////////////////////////////////////////////// // Compute load integration time int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); loadlength = loadlength + readoutdead; int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int jitterdead = GetMaxTimeJitter(band,reffreq); // Integration time per frequency and pointing int on_inttime = 2 * n_chop_on * data_time; int off_inttime = 2 * n_chop_off * data_time_off; // Duration of initial set up // Staying at the same frequency makes no sense here. // First frequency point double runningfreq = freqgrid[grouporder[1][0]]; // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,runningfreq,false); } initlength = initlength + loadlength; // Tuning delays int bigtunestep = duration(HIFIRetuneFreq(band,reffreq,reftarget)); // Correct for variation within the band int tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq); bigtunestep = bigtunestep + tunediff; // As step within a group could be faster than a large step if(n_freq_point > 1) { int smallstep = duration(HIFIChangeFreq(band,reffreq)); } else { smallstep = bigtunestep; } // For double phases I can use the added jitterdead in both phases for tune int auxtunestep = bigtunestep - jitterdead; int halftunestep = (auxtunestep + 1) / 2; // Telescope pointing int on_pointing = n_freq_point * on_inttime + (n_freq_point - 1) * smallstep + halftunestep + jitterdead; int off_pointing = off_inttime + halftunestep + jitterdead; // Check load_interval allowance int scan_time = 2 * imax(on_pointing,off_pointing); if(scan_time > load_spacing) { SError("Load interval of " + load_interval + "s is exceeded by " + n_chop_on * n_freq_point + " chop cycles."); } // Estimate of the load-cycles to issue a representative // telescope command if(n_cycles > 1) { // How often do I have to perform a load slew int n_loadinterval = imax(load_interval / scan_time,1); // fit with n_cycles n_loadinterval = imin(n_loadinterval,n_cycles); n_loadinterval = IMultiple(n_loadinterval,n_cycles); } else { n_loadinterval = 1; } // recompute load length during slews in case of short integrations // This regime must be maintained in the post_timing if(n_loadinterval <= 1) { loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,false,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; } // No dangling needed in this mode - we stop halftunelength before telescope int dangling = 0; bool end_load_on = false; bool end_load_off = false; // Return all the times needed for telescope call and post_timing processing return {{on_inttime,off_inttime,on_pointing,off_pointing,loadlength,auxtunestep,load_spacing,n_loadinterval,n_chop_on,n_chop_off,data_time,data_time_off,end_load_on,end_load_off,initlength,dangling},spectralparms}; } //////////////////////////////////// // Routine to provide initial guesses for sequence parameters // Load chop mode without baseline calibration // {string,double,double}[] procedure HifiPointProcLoadChopNoRefSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int data_time_guess = imin(imax(iceil(0.3 * allan_time_lores),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Contruct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)}]; return retvalues; } // Noise ratio from an OTF observation // double procedure OtfNoiseRatio { double n = 10.0; // number of points in one scan double[] parameters = [0.02,0.4,0.05,0.667,2.5]; // Parameters: integration time, delay, slew from OFF relative to Allan time, ratio of t_off time to sqrt(n)*t_on, drift exponent }{ {double,double} noisevalues = OtfNoiseValues(n,parameters); double y = noisevalues{1} / noisevalues{0}; return y; } // Slow chop integration at OFF position ON-OFF-OFF-ON... block HIFISlowChopOffIntegration HIFI 6032 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3left","chop_M3right"],rates); } // Procedure used by the spectral scan sequencer to compute the // maximum frequency group length int procedure SpotSpectralScanGroupLength { string band = "4a"; double lo_freq1 = 978.2; double lo_freq2 = 979.6; int redundancy = 4; }{ // start Volkers list double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz // general definitions double factorMHzPerGHz = 1000.0; // start translation lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; // Call CUS routine int grouplen = GetSpectralScanGroupLength(band,lo_freq,lo_freq_up,redundancy); return grouplen; } ///////////////////////////////////////////////////////////////// // get reference frequency, resolution, redundancy {{bool,int,double[],bool[]},{bool,int,double[],bool[]}} procedure GetSpectralScanHRS { int redundancy = 4; // Redundancy of overall spectral scan string band = "4a"; // HIFI band }{ string calibfile = "spectralscan_hrs"; string sredun = "" + redundancy; // Use generic reader double[] hrsset = SpectralScanReader("fscanhrs",["resolution","hrs1_offset","hrs2_offset"],band,redundancy); int hrsresol = iround(hrsset[0]); double hrs1_offset = hrsset[1]; double hrs2_offset = hrsset[2]; // Fill into normal structure double[][] hrspositions = SpreadHRS(band,[hrsresol,hrsresol],[hrs1_offset,hrs2_offset]); {bool,int,double[],bool[]} hrs1 = {true,hrsresol,hrspositions[0],[true,true,true,true]}; {bool,int,double[],bool[]} hrs2 = {true,hrsresol,hrspositions[1],[true,true,true,true]}; return {hrs1,hrs2}; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure SScanDBS_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int allsteps = 4; // Total number of frequency pointing periods int freqsteps = 4; // Total number of frequencies double avnumchop = 1.0; // Average number of chop cycles per frequency double tscan = 60.0; // Total average duration of one cycle {double,double,double} tact = {10.0,4.9,0.05}; // Field of actual dead and integration times }{ double inttimeperphase = tact{1}; // Actual integration time in one phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); // Use DSB noise for long spctral scans if(dsb) { double idealnoiselsb = idealvalues{1} * idealvalues{1}; double idealnoiseusb = idealvalues{3} * idealvalues{3}; double idealnoise = idealnoiselsb * idealnoiseusb / (idealnoiselsb + idealnoiseusb); } else { idealnoise = idealvalues{1} * idealvalues{1}; } double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for range coverage double accumulation = double(freqsteps) / double(nfreq); idealnoise = idealnoise * accumulation; double efficiency = idealnoise / obsnoise; // Compute the actual integration time double maxsteps = max(double(freqsteps),double(allsteps)); double posinttime = maxsteps * inttimeperphase * 2.0 * avnumchop; int instrumenttime = iceil(double(allsteps) * tscan); // Check total integration time double timeefficiency = 2.0 * posinttime / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posinttime,timeefficiency,efficiency,relnoise,dsb); } // Get frequency resolution needed to measure standing wave pattern // in chop measurements double procedure GetChopSWResolution { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("chopswresolution",["resolution"],band,lo_freq); return dead[0]; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure FastDBSRaster_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval int n_int = 20; // number of integrations in one data dump interval int n_data = 3; // number of chop cycles in one integration int n_load = 0; // number of integrations in one pointing phase int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Special meaning of n_load here if(n_load == 0) { int n_seq = 1; } else { n_seq = n_load; } // Compute parameters for the instrument timing {double,double} tinst = GetInstDeadFastChop(data_time,n_int,n_data,band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * n_data) - tinst{0}; // subtract dead times in switches // only half of them are subtracted due to ABAB scheme tdeadint = tdeadint - double(n_int * n_data) * tinst{1}; // Total dead time per cycle, only one point still not covered double tdead_tot = tdead + double(2 * n_seq) * tdeadint; // Integration time double tphaseint = tinst{0} / double(2 * n_int * n_data); return {tdead_tot,tphaseint,tinst{1}}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure JupiterDBS_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_seq = 1; // Number of continuous chop cycles int n_load = 0; // additional load measurements in one pointing phase int n_loadinterval = 10; // number of nods before a load measurement bool end_load = false; // Need for load after each pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration int shiftlength = 10; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"jupiter"); } delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load) { HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Second phase in first nod position // occurs for even cycle numbers runintostate = false; if(state[2] % 2 == 0) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 7) { // second nod position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i2 = 1 .. n_load) { // Use asymmetric scheme now to minimize setup uncertainties HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // First phase in second nod position // occurs for odd cycle numbers runintostate = false; if(state[2] % 2 == 1) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement // ( Does not occur if end_load is set) LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } {int,double,double,double,double,double} procedure HifiIdealMode { string modeName = "pos"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // Get parameters which are needed double center_lo_freq = 0.5 * (lo_freq + lo_freq_up); double tsys = InterpolateTsys(band,center_lo_freq); double eta_mb = InterpolateCoupling(band,center_lo_freq); double[] gssb = InterpolateGssb(band,center_lo_freq); double phasetime = double(goalTime); double noiseratio = 0.0; // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(1.0 / (effResolution{1} * 1000000.0 * phasetime)); double dsbnoise_hires = tsys * sqrt(1.0 / (effResolution{0} * 1000000.0 * phasetime)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // return total time with initial slew int returntime = goalTime; // Originally I had added 180s from telescope // Now make corrections for maps or spectral scans if(npoints * nlines > 1) { double factor = sqrt(double(nlines * npoints)); usbnoise_lores = usbnoise_lores * factor; usbnoise_hires = usbnoise_hires * factor; lsbnoise_lores = lsbnoise_lores * factor; lsbnoise_hires = lsbnoise_hires * factor; } if(lo_freq_up > lo_freq) { {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq,lo_freq_up,redundancy,0.0,1); factor = sqrt(double(fqparms{0} / fqparms{4})); usbnoise_lores = usbnoise_lores * factor; usbnoise_hires = usbnoise_hires * factor; lsbnoise_lores = lsbnoise_lores * factor; lsbnoise_hires = lsbnoise_hires * factor; } // Return noise values and the maximum ratio of drift to radiometric noise return {returntime,usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } ////////////////////////////////////////////////////////////////////////// // special setup using the new frequency calibration - to be removed again ////////////////////////////////////////////////////////////////////////// // Procedure for zero and comb measurement // Collects all common parts for LoadMeasurement and DoubleLoadMeasurement // procedure ZeroCombMeasurement_FCal { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency int used_datatime = 4; // time between subsequent data readouts in load {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Usage of WBS bool wbs1used = backendreadoutparms{2}{0}; bool wbs2used = backendreadoutparms{3}{0}; // Zero and Comb measurement is only used in WBS observations if(wbs1used || wbs2used) { // Now start the zero-comb measurement int danglingreadout = WBS_Zero_FCal(band,lo_freq); // Add possible delay needed before next zero measurement if(used_datatime < danglingreadout) { delay(danglingreadout - used_datatime); } } } // Routine to extract the settings for the two HK regimes string[] procedure QueryHKPattern { bool active = false; // Whether to actively query the spectrometers }{ // HK pattern according to SRON-U/HIFI/SP/2001-001 4.3.2 PDU status if(active) { int pattern = ifloor(dlookup("datarates","allreadpattern","value")); } else { pattern = ifloor(dlookup("datarates","noreadpattern","value")); } // translate into new mask of arguments string[] mask = ["OFF","OFF","OFF","OFF","OFF","OFF"]; for(int i = 0 .. 5) { if(pattern % 2 > 0) { mask[i] = "ON"; } else { mask[i] = "OFF"; } pattern = pattern / 2; } return mask; } {int,double,double,double,double,double} obs HifiPointModePositionSwitch { string modeName = "pos"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,5]; // data dump interval limited by the data rates int n_int_on = 3 in [2,1800]; // number of data dumps for integration per phase int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-PositionSwitch",{data_time,0,n_int_on,0,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing = PositionSwitch_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double} post_timing = PositionSwitch_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{7}; bool final_load = post_timing{1}{12}; double tscan = post_timing{2}; double tdead = post_timing{3}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { PositionSwitch_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,startobs,telescopetimes,n_loadinterval,loadlength,final_load); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument double tdead_tot = PositionSwitch_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_cycles,tscan,tdead_tot); // Evaluate performance PositionSwitch_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,tscan,tdead_tot); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ///////////////////////////////////////////////////////////////// // Slow chop dual beam switch observing mode - special version for Jupiter // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiPointProcJupiterDBS { /* Setup parameters */ int naifid = 0; // Tracing object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-Jupiter-DBS",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer // Two changes relative to the normal DBS // 1) The longer load duration is enforced by zero resolution {double,double} loadResolution = {0.0,effResolution{1}}; // 2) I assume that the tuning duration does not depend on the tuning level // so that the normal pre_timing can be reused. {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = DBS_pre_timing(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} post_timing = DBS_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_seq = post_timing{1}{8}; int n_loadinterval = post_timing{1}{7}; bool end_load = post_timing{1}{9}; int shiftlength = post_timing{1}{10}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { JupiterDBS_commanding(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,n_loadinterval,end_load,final_load,startobs,telescopetimes,loadlength,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = DBS_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBS_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_seq * (n_load + 1),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // Frequency switch observing mode without baseline calibration // // All properties inherited from the load-chop mode // // This whole implementation is highly speculative as we have no experience // with frequency switch measurements yet. // {int,double,double,double,double,double} obs HifiPointProcFSwitchNoRef { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-FSwitch-NoReference",{data_time,0,0,0,0,0,0,0,n_cycles,load_interval}); // Two cases: fine pointing or position switch // Call first part of the timing computer {int,int,int,int,int,int,bool,int,int} pre_timing_f = FSwitchNoRef_pre_timing(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,pre_timing_f); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing_f = SingleChopNoRef_post_timing(pre_timing_f,telescopetimes); // Now the actual observation starts // Prepare telescope command tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,post_timing_f{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Consistency check int totaltime = post_timing_f{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// // standard parameters for fine pointing int loadlength = post_timing_f{1}{2}; int n_per_on = post_timing_f{1}{4}; int n_load_on = post_timing_f{1}{5}; bool end_load_on = post_timing_f{1}{6}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FSwitchNoRef_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on,n_load_on,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = FSwitchNoRef_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_per_on * (n_load_on + 1),tscan,tdead); // Evaluate performance SingleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_per_on * (n_load_on + 1),true,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {string,double,double}[] procedure HifiMappingModeDBSRasterSequencerInit { string modeName = "raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Combine points for n_switch=1 int main_phase = iceil(phaselengths{0}); int n_pointsperscan_guess = imin(imax(main_phase / (2 * data_time_guess),1),npoints * nlines); int n_pointsperscan_range = 1 - n_pointsperscan_guess; if(n_pointsperscan_range == 0) { n_pointsperscan_range = 1; } // remaining part for n_switch int n_switch_on_guess = main_phase / (n_pointsperscan_guess * 2 * data_time_guess) + 1; int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_pointsperscan",double(n_pointsperscan_guess),double(n_pointsperscan_range)}]; return retvalues; } // Change LO frequency but keep backend configuration - used in spectral scans // // Currently, no adaption to a full HK reading is implemented here procedure HIFIRetuneFsw { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency ion MHz double freq_throw = -40.0; // throw of frequency switch in MHz string level = "sscan_normal"; // Name of target level }{ ConfigureFPU(band,lo_freq + freq_throw / 2.0,false); HIFITuneFreqFsw(band,lo_freq,lo_freq + freq_throw,true,level); } // LCU configuration AT START-UP into NOMINAL mode, procedure // This version assumes cold FPU but warm LO without attenuators // It ensures the right frequency is picked up for a given band procedure LCU_switchon_proc_aot { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; // LO frequency in GHz }{ // //Fetch LO parameters string name_configlo = "name_configlo_a"; string name_configlcu = "name_configlcu_a"; string name_confindex = "name_confindex_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlcu = "name_configlcu_b"; name_confindex = "name_confindex_b"; name_configlo = "name_configlo_b"; } // {double,string}[] result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step"],band,lo_freq); double plevel_v = result[0]{0}; double m1_v = result[1]{0}; double m2_v = result[2]{0}; double m3_v = result[3]{0}; int d2_step = iround(result[4]{0}); // double[] result_d = CalibrationReader("name_lcu_safe_values",["g1_v","g2_v","d1_v","d2_v"],band,0.0); double gate1_v = result_d[0]; double gate2_v = result_d[1]; double drain1_v = result_d[2]; double drain2_v = result_d[3]; // result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq); int freq_nx = ifloor(result[0]{0}); //Compute lsu_main and offset int[] resu = ComputeLSU_A_M_R(band,lo_freq); int lsu_main = resu[0]; int lsu_offset = resu[1]; //Get checksum result = ConfigurationReader("name_delays",["cus_checksum"],band,lo_freq); int macro_checksum = iround(result[0]{0}); // result = ConfigurationReader(name_configlo,["curlim1_v","curlim2_v"],band,lo_freq); string curlim1_v = result[0]{1}; string curlim2_v = result[1]{1}; // result = ConfigurationReader("name_delays",["switch_on_delay","config_lo_delay"],band,lo_freq); int switch_on_delay = iround(result[0]{0}); int config_lo_delay = iround(result[1]{0}); // result_d = CalibrationReader("name_lcu_safe_values",["d2_v"],band,0.0); drain2_v = result_d[0]; // //Recovey from potential failure mode Set_LO_Nominal_block_aot(); // //Send command: expect that we have already switched to NOMINAL //We set D2 to best guess and wait some time to stabilize chain temperature HIFI_Configure_LCU_block_aot(band,lo_freq,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum,switch_on_delay); // //TM page dump and error flag clearance now contained in the above block //Set heater to their switch-on value HL_heater_block_aot(band,"nominal"); } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command for the DBS cross observing mode // // As I have to set up the nodding pattern by hand, the cross must be // defined in instrument coordinates - implies further restrictions // {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} procedure DBSCross_telescope { int naifid = 0; // Tracing object ID {double,double} mapcenter = {0.0,0.0}; // Coordinates of the center of the map double stepsize = 0.0050; // Distance between subsequent points in the raster line int npoints = 10; // Number of horizontal points string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string throw = ""; // Identifier for chop throw, empty is standard {int,int,int,int,int,int,int,int,int,int,int,int,int} timing = {4,10,4,21,1,1800,0,10,1,1,1,50,0}; // full timing parameter list int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles }{ // Assign values int pointing = timing{1}; int loadlength = timing{3}; int holdlength = timing{4}; int n_loadinterval = timing{7}; int n_pointsperscan = timing{10}; int initlength = timing{11}; int dangling = timing{12}; // Create variables for telescope command string ib = GetBoresight(band,lo_freq,true); // A change of ra-dec depending on naifid may be needed double ra = mapcenter{0}; double dec = mapcenter{1}; // Pattern angle and throw of the chopper direction // The nodding angle should always be parallel to the chopper double[] chopper = GetSkyChopThrow(band,lo_freq,throw); double nodlength = chopper[0]; double pattnod = chopper[1]; nodlength = max(nodlength * 3600.0,2.0); // Map in instrument coordinates here to allow addition // (nod is always in instrument coordinates by default) bool fixed = false; double patt = pattnod; // Map parameters double d1 = stepsize * 3600.0; double d2 = d1; // Create first array of relative coordinates double[] xoff = []; double[] yoff = []; double x0 = -double(npoints - 1) / 2.0 * d1; double y0 = -double(npoints - 1) / 2.0 * d2; for(int i1 = 0 .. npoints - 1) { xoff[i1] = x0 + double(i1) * d1; yoff[i1] = 0.0; } // Currently the center point is observed twice - this may change for(int i2 = 0 .. npoints - 1) { xoff[i2 + npoints] = 0.0; yoff[i2 + npoints] = y0 + double(i2) * d2; } int numscans = length(xoff) / n_pointsperscan; // Initialization int icount = 0; int ioff = 0; int bphase = 0; double[] yarr = []; double[] zarr = []; int[] tp = []; // Now turn into array of pointings to be used if(n_pointsperscan > 1) { // Nodding OF raster int knod = 0; int nnod = 1; for(int i_cycle = 0 .. n_cycles - 1) { for(int i_scan = 0 .. numscans - 1) { for(int phasecount = 0 .. 1) { bphase = (bphase + phasecount) % 2; for(int i_point = 0 .. n_pointsperscan - 1) { // Go to second nod only in B phases zarr[icount] = xoff[ioff] + double(bphase) * nodlength; yarr[icount] = yoff[ioff]; tp[icount] = pointing; icount = icount + 1; ioff = ioff + 1; } // Get points the second time in second phase ioff = ioff + (phasecount - 1) * n_pointsperscan; } } // End of map ioff = 0; } // Consistency check if(length(yarr) != 4 * npoints * n_cycles) { CError("Custom map point number does not cover requested cross."); } // Treat all load slews as holds int nload = 0; int nhold = 2 * n_loadinterval * n_pointsperscan; // no hold if period too long if(nhold > 4 * npoints * n_cycles) { nhold = 0; } } else { // Nodding IN raster knod = 1; nnod = n_cycles; for(int ipoint2 = 0 .. numscans - 1) { zarr[ipoint2] = xoff[ipoint2]; yarr[ipoint2] = yoff[ipoint2]; tp[ipoint2] = pointing; } // Treat load slew either as load or as hold depending on n_cycles if(n_loadinterval > n_cycles) { nload = 0; nhold = n_loadinterval / n_cycles; // no hold if period too long if(nhold > numscans) { nhold = 0; } } else { nload = n_loadinterval; nhold = 0; } } // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(pointing < 10) { SError("Pointing phase length too short. Increase the number of integrations."); } if(length(yarr) > 3000) { IError("Map too large for cross mode. Reduce the number of points."); } if(nodlength > 960.0) { IError("Nodding length too long. Choose a smaller chop throw."); } // repetition at multiple frequencies not yet implemented: int trep = 0; int n_repeat = 0; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,fixed,patt,0.0,0.0,yarr,zarr,tp,pattnod,nodlength,nnod,knod,loadlength,nload,holdlength,nhold}; } ////////////////////////////////////////////////////////////////////////////// // routines needed for IST, but not part of observing modes ////////////////////////////////////////////////////////////////////////////// //Set HIFI to standby II - laser status handled by configwbs.config //It will switch off LO and let in into stanby. Lasers and HBB kept ON obs HifiEngSetIntoStandby_II { }{ // pre_timing {int,int} pre_timing = Eng_pre_timing(); int initlength = pre_timing{0}; int closelength = pre_timing{1}; int mainduration = duration(HifiIntoStandby_II()); // telescope command int[] ts = no_pointing(true,initlength,closelength,mainduration); }{ // Instrument commanding - use state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 2) { // Initialization HIFIInitObs(); HIFISetHK("fast",true); } if(state[0] == 3) { // ON integration HifiIntoStandby_II(); } if(state[0] == 5) { HIFISetHK("normal",true); HIFICloseObs(); } } } //Check that drain2 is below blue max and above blue min double procedure Check_BLUE_LIMIT_D2_proc_fm { string band = "4a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO Frequency double drain2_v = 1.4; //Current drain2 to compare to blue limits }{ //Check against blue max //Implementation of SCR-2220 double drain2_max = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq); // double drain2_v_new = drain2_v; if(drain2_v > drain2_max) { drain2_v_new = drain2_max; //this already accounts for the margin message("Warning: drain2 was commanded above its blue max"); } //Check against blue min //Implementation of SCR-2220 double drain2_min = Get_BLUE_MIN_D2_proc_fm(band,lo_freq); // if(drain2_v < drain2_min) { drain2_v_new = drain2_min; message("Warning: drain2 was commanded below its blue min"); } return drain2_v_new; } //////////////////////////////////////// // Procedure to calculate the post timing // {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} procedure DBS_post_timing { {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = {4,10,4,21,11,1800,0,32,1,false,0,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,20,1,21,0]; int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles }{ // Get all values from the pre_timing section int inttime = pre_timing{0}; int pointing = pre_timing{1}; int readouttime = pre_timing{2}; int loadlength = pre_timing{3}; int jitterdead = pre_timing{4}; int load_spacing = pre_timing{5}; int n_load = pre_timing{6}; int n_loadinterval = pre_timing{7}; int n_seq = pre_timing{8}; bool end_load = pre_timing{9}; int shiftlength = pre_timing{10}; int initlength = pre_timing{11}; int dangling = pre_timing{12}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to OFF int longslew = telescopetimes[4]; // Actual slew time for load slew int pointwaittime = telescopetimes[3]; // Idle time between two phases int tend = telescopetimes[5]; // Final deceleration time ////////////////////////////////////////////////////////////////// // Now we start the actual computations // Add pointwaittime to slew dead time in cycles slewtime = slewtime + pointwaittime; longslew = longslew + pointwaittime; // If load is performed between the cycles use pointwaittime for load if(end_load) { int halfloadlength = (loadlength - jitterdead + 1) / 2; int effhalfloadlength = (loadlength - jitterdead - pointwaittime + 1) / 2; int subtracted = halfloadlength - effhalfloadlength; pointing = pointing - subtracted; shiftlength = effhalfloadlength; } // Now we can compute the true scan time int scan_time = 2 * pointing + slewtime; // Finally I can compute the load interval n_loadinterval = imax((load_spacing + slewtime) / scan_time,1); // Compute duration of measurement and average scan length // Compute total dead time in one pointing cycle including load overhead int scan_time_long = 2 * pointing + longslew; int n_long = n_cycles / n_loadinterval; int looplength = (n_cycles - n_long) * scan_time + n_long * scan_time_long; double tscan = double(looplength) / double(n_cycles); // Get pointing dead time, instrument dead time is added later double tdead = tscan - double(2 * inttime); // Determine need for final load measurement double rest = double(n_cycles % n_loadinterval) + 0.5; bool final_load = rest > 0.5001 * double(n_loadinterval); // Compute total duration initlength = initlength - shiftlength; // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int totaltime = looplength; // Add dangling load time, either of the two can apply, but // they are mutually exclusive, otherwise the readoutdelay applies if(final_load) { dangling = loadlength; } if(end_load) { dangling = loadlength - shiftlength; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute total duration, remove pointwaittime for last slew totaltime = totaltime + dangling - pointwaittime + tend; // show gyro-propagation messages GCPMessages(pointing,2 * scan_time_long,tend); // Return all the times needed in the observing mode modules // The second tuple contains the modified pre_timing parameters, // the rest the newly computed parameters return {totaltime,{inttime,pointing,readouttime,loadlength,jitterdead,load_spacing,n_load,n_loadinterval,n_seq,end_load,shiftlength,initlength,dangling},final_load,tscan,tdead}; } // Mirror an angular direction double procedure MirrorDirection { double angle = 0.0; // Original angle }{ double fullcircle = 360.0; return (angle + fullcircle * 0.5) % fullcircle; } ///////////////////////////////////////////////////////////////// // Spectral scan in load-chop with OFF calibration // {string,double,double}[] procedure HifiSScanProcLoadChopSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half load-sky-sky-load cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of LoadChop modes {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double,double,double} phaselengths = LoadChopPhaseLengths(band,lo_freq,effResolution,narrowReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // How much time for single ON phase int n_switch_on_guess = imax(iceil(2.0 * phaselengths{0} / ((double(n_freq_point_guess) + sqrt(double(n_freq_point_guess))) * 2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * sqrt(double(n_freq_point_guess)) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } ///////////////////////////////////////////////////////////////// // Derived parameters // Procedure used by the spectral scan sequencer to compute the // maximum frequency group length int procedure GetSpectralScanGroupLength { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy }{ // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq_low,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // Compute group length double central_freq = 0.5 * (lo_freq_low + lo_freq_up); double nocaliblen = GetFNoCalibLength(band,central_freq); int grouplen = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); return grouplen; } ///////////////////////////////////////////////////////////////// // Spectral scan in load chop without OFF calibration // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiSScanProcLoadChopNoRef { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-SScan-LoadChop-NoReference",{data_time,0,0,0,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanLoadChopNoRef_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,n_cycles,n_freq_point,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar = Fine_telescope(naifid,onPosition,band,reffreq,pre_timing{0}); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing = SScanChopNoRef_post_timing(pre_timing{0},telescopetimes); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = Fine_telescope(naifid,onPosition,band,reffreq,post_timing{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int loadlength = post_timing{1}{2}; int n_per_on = post_timing{1}{4}; int n_load_on = post_timing{1}{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanLoadChopNoRef_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_per_on,n_load_on,groupnumber,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("lchop",band,reffreq,hr1,hr2,wb1,wb2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = SScanChopNoRef_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,n_per_on * imax(n_load_on,1),false,tscan,tdead); // Evaluate performance SScanChopNoRef_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_per_on * imax(n_load_on,1),groupnumber * n_freq_point,false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // HRS partial configuration, block // Configures the resolution mode block HRS_config_resol_block_aot HIFI 6618 { string band = "4a"; // HIFI band string[] hrs_mode = ["wb","wb"]; //HRS resolution code }{ //////////////////////////////////////////////////////////////////// //Now Configure blocks //H-polar string hrs_filename_h = "name_confighrs_" + hrs_mode[0]; {double,string}[] result = ConfigurationReader(hrs_filename_h,["hrh_block_1","hrh_block_2","hrh_block_3","hrh_block_4","hrh_block_5","hrh_block_6","hrh_block_7","hrh_block_8"],band,0.0); string hrh_block_1 = result[0]{1}; string hrh_block_2 = result[1]{1}; string hrh_block_3 = result[2]{1}; string hrh_block_4 = result[3]{1}; string hrh_block_5 = result[4]{1}; string hrh_block_6 = result[5]{1}; string hrh_block_7 = result[6]{1}; string hrh_block_8 = result[7]{1}; // result = ConfigurationReader("name_delays",["hrs_config_delay"],band,0.0); int hrs_config_delay = iround(result[0]{0}); // Hifi_HIFI_Config_HRS_H_blocks($BBID,hrh_block_1,hrh_block_2,hrh_block_3,hrh_block_4,hrh_block_5,hrh_block_6,hrh_block_7,hrh_block_8); //delay(hrs_config_delay); // //V-polar string hrs_filename_v = "name_confighrs_" + hrs_mode[1]; result = ConfigurationReader(hrs_filename_v,["hrv_block_1","hrv_block_2","hrv_block_3","hrv_block_4","hrv_block_5","hrv_block_6","hrv_block_7","hrv_block_8"],band,0.0); string hrv_block_1 = result[0]{1}; string hrv_block_2 = result[1]{1}; string hrv_block_3 = result[2]{1}; string hrv_block_4 = result[3]{1}; string hrv_block_5 = result[4]{1}; string hrv_block_6 = result[5]{1}; string hrv_block_7 = result[6]{1}; string hrv_block_8 = result[7]{1}; // Hifi_HIFI_Config_HRS_V_blocks($BBID,hrv_block_1,hrv_block_2,hrv_block_3,hrv_block_4,hrv_block_5,hrv_block_6,hrv_block_7,hrv_block_8); // //Wait delay to allow all setting to be configured delay(hrs_config_delay); } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of peakup mode {int,int,int,int,int,double,int,int} procedure Peakup_pre_timing { int nlines_tot = 3 in [1,100]; // Number of rows in the map int npoints = 3 in [2,100]; // Number of points per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {false,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {false,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {false,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed parameters for peak-up int data_time = 3; // Data dump period int n_chop = 1; // Number of chop cycles double eff_resolution = 1.6; // Reference resolution for load measurement int peakuptime = 3; // Time neede for peakup integration // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); // Compute parameters for the instrument timing int jitterdead = GetMaxTimeJitter(band,lo_freq); int inttime = 2 * n_chop * data_time; // integer integration time int pointing = inttime + peakuptime + jitterdead; // Pointing time // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution,data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Duration of initial set up int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); initlength = initlength + duration(HifiPeakupConfigure(data_time,n_chop,true,band,lo_freq,0.0,backendreadoutparms)); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; initlength = initlength + loadlength; // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {inttime,pointing,data_time,loadlength,n_chop,eff_resolution,initlength,dangling}; } ///////////////////////////////////////////////////////////////////// // Procedure to generate the fine pointing telescope command for the // observing mode {int,int,int,string,int,double,double,double,double,int} procedure Fine_telescope { int naifid = 0; // Tracking object ID {double,double} onposition = {0.0,0.0}; // Coordinates of the source string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {int,int,int,int,int,int,bool,int,int} timing = {16,16,21,1800,2,0,false,50,0}; // timing parameter list }{ // Assign values int on_pointing = timing{1}; // Pointing time int initlength = timing{7}; // Initial setup time int dangling = timing{8}; // Final load measurement // Create variables for telescope command string ib = GetBoresight(band,lo_freq,false); // A change of ra-dec depending on naifid may be needed double ra = onposition{0}; double dec = onposition{1}; // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(on_pointing > 50000) { IError("Pointing too long. Break up the observation into smaller pieces."); } // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,0.0,0.0,on_pointing}; } int block HIFI_DoubleCalibrate_hot_cold HIFI 6006 { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency int data_time = 4; // time between subsequent data readouts int n_data = 2; // Integration time counter {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 bool staycal = false; // whether we should stay at the hot load at the end }{ // data rate and read-out time {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int readout = dataparms{0}; // send the configure spectroscopy command to configure the measurement // returned dead times not needed here ConfigureSpectroscopy(data_time,n_data,"hot-cold",band,lo_freq,backendreadoutparms); // Switch to first FSW register Hifi_HIFI_HL_set_FSW1($BBID); // Spectroscopy should start at first bus slot delay(1); // Perform first slow-chop HIFI_Spectr_slow_chop_proc_aot(data_time,n_data / 2,band,lo_freq,["chop_hot","chop_cold"],dataparms{1}); // Switch to second FSW register Hifi_HIFI_HL_set_FSW2($BBID); // delay required at the end int sdelay = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Clean up for next spectroscopy delay(sdelay); // integrate HIFI_Spectr_slow_chop_proc_aot(data_time,n_data / 2,band,lo_freq,["chop_hot","chop_cold"],dataparms{1}); if(!staycal) { // Switch to back FSW register Hifi_HIFI_HL_set_FSW1($BBID); // Move chopper back to the sky RotateChopper(band,lo_freq,"chop_M3"); } // have clean bus timing for next spectroscopy block delay(sdelay); return readout; } // Routines for calibration data handling ///////////////////////////////////////////////////////////////// // Routines using the generic reader // A possible frequency dependence is hidden behind the reader ///////////////////////////////////////////////////////////////// // Interpolate gain in corresponding sideband for the selected frequency double[] procedure InterpolateGssb { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] gssb = CalibrationReader("gain",["Gusb","Glsb"],band,lo_freq); return gssb; } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command for the Peakup mode {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double} procedure Peakup_telescope { int naifid = 0; // Tracing object ID {double,double} mapcenter = {0.0,0.0}; // Coordinates of the center of the map double stepsize = 0.0050; // Distance between subsequent points in the raster line int nlines = 1; // Number of rows in the map; int npoints = 10; // Number of points per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {int,int,int,int,int,double,int,int} timing = {8,10,2,21,4,1.6,50,0}; // timing parameter list }{ // Assign values int pointing = timing{1}; int initlength = timing{6}; int dangling = timing{7}; // Create variables for telescope command string ib = GetBoresight(band,lo_freq,false); // A change of ra-dec depending on naifid may be needed double ra = mapcenter{0}; double dec = mapcenter{1}; // Map always in spacecraft coordinates, always start in +Z direction bool fixed = false; double patt = 0.0; // Map parameters double rowstep = 0.5 / 3600.0; double d1 = double(iceil(stepsize / rowstep)) * rowstep * 3600.0; // Exception for the "impossible" case of spacings below 2arcsec d1 = max(d1,2.0); // Always isotropic for peakup double d2 = d1; // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(pointing < 10) { SError("Pointing phase length too short. Increase the number of integrations."); } if(d1 > 480.0) { IError("Raster spacing too coarse. Increase the sampling."); } // parameters for OFF position - not used int koff = 0; int toff = 0; double raoff = 0.0; double decoff = 0.0; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,fixed,patt,0.0,0.0,npoints,nlines,d1,d2,pointing,koff,toff,raoff,decoff}; } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure PositionSwitch_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int n_cycles = 1; // Number of map coverages double tscan = 60.0; // Total average duration of one scan double tdead = 10.0; // Average dead time in one slew }{ double inttime = (tscan - tdead) / 2.0; // Integration time per pointing phase // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = TwoPhaseNoise(inttime / allan_time_lores,[tdead / allan_time_lores,alpha]); double systemnoise_hires = TwoPhaseNoise(inttime / allan_time_hires,[tdead / allan_time_hires,alpha]); double noiseratio = TwoPhaseNoiseRatio(inttime / allan_time_lores,[tdead / allan_time_lores,alpha]); // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 1000000.0 * double(n_cycles) * tscan)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 1000000.0 * double(n_cycles) * tscan)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } // Configuration for continuous integration block HIFIConfigureContIntegration HIFI 6020 { int data_time = 4; // Integration time between two data readouts int n_int = 1; // Integration time counter string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Call procedure doing the work ConfigureSpectroscopy(data_time,n_int,"tp",band,lo_freq,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure FSwitchNoRef_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int n_cycles = 1; // Number of map coverages double tscan = 60.0; // Total average duration of one scan double tdead = 10.0; // Average dead time in one slew }{ // Call position switch noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,eff_resolution,oneGHzReference,n_cycles,tscan,tdead); // Correct for signal in both phases double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; // Return noise values and the maximum ratio of drift to radiometric noise return {noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // procedure called to get the instrument into standby // with WBS lasers Off and HBB ON procedure HifiIntoStandby_I { }{ //FPU stand-by with HBB On Init_MSA_aot("0","CLOSE",0.0,true,"ON"); //WBS stand-by with laser OFF WBS_standby_block_aot("OFF"); //HRS should already have max att. and locked LO //done during the power-on., or via StandbyII } {string,double,double}[] procedure HifiMappingModeFSwitchOTFSequencerInit { string modeName = "fs-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = FSwitchPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities // Main loop int main_phase = iceil(phaselengths{0}); // How many lines could we do at most? int n_linesperscan_guess = main_phase / (2 * datalimit) + 1; n_linesperscan_guess = imax(n_linesperscan_guess * n_linesperscan_guess / npoints,1); // restrict the scan size if(nlines == 1 && n_linesperscan_guess > 1) { n_linesperscan_guess = 2; } else { n_linesperscan_guess = IMultiple(n_linesperscan_guess,nlines); n_linesperscan_guess = imin(n_linesperscan_guess,nlines); } int n_linesperscan_range = 1 - n_linesperscan_guess; if(n_linesperscan_range == 0) { n_linesperscan_range = 1; } double n_pointsperscan = double(n_linesperscan * npoints); // Compute back int int_time_guess = main_phase / iceil(sqrt(n_pointsperscan)); int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int n_switch_on_guess = imax(int_time_guess / (2 * data_time_guess),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } data_time_guess = imax(imin(5,int_time_guess / (2 * n_switch_on_guess)),datalimit); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * 0.67 * sqrt(n_pointsperscan) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_linesperscan",double(n_linesperscan_guess),double(n_linesperscan_range)}]; return retvalues; } ///////////////////////////////////////////////////////////////// // Spectral scan in frequency switch with OFF calibration // {string,double,double}[] procedure HifiSScanProcFSwitchSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of Frequency switch modes {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double,double,double} phaselengths = FSwitchPhaseLengths(band,lo_freq,effResolution,narrowReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // How much time for single ON phase int n_switch_on_guess = imax(iceil(2.0 * phaselengths{0} / ((double(n_freq_point_guess) + sqrt(double(n_freq_point_guess))) * 2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * sqrt(double(n_freq_point_guess)) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } {int,double,double,double,double,double} obs HifiMappingModeFastDBSCross { string modeName = "cross"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-FastChop-DBS-Cross",{data_time,0,n_switch_on,n_int_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(2,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = custom_map_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSCross_post_timing(pre_timing,telescopetimes,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = custom_map_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int scansize = post_timing{1}{10}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastDBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,true); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,2,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Correct for double counting of central point // The central point is returned only double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; noisevalues{4} = noisevalues{4} / multiplier; // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure PositionSwitch_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int n_cycles = 1; // Number of map coverages double tscan = 60.0; // Total average duration of one scan double tdead = 10.0; // Average dead time in one slew }{ double inttime = (tscan - tdead) / 2.0; // Integration time per pointing phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; double efficiency = idealnoise / obsnoise; // Compute integration time double posinttime = inttime * double(n_cycles); double timeefficiency = 2.0 * posinttime / double(totaltime); // Drift noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posinttime,timeefficiency,efficiency,relnoise,false); } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command for the DBS raster observing mode {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} procedure DBSRaster_telescope { int naifid = 0; // Tracing object ID {double,double} mapcenter = {0.0,0.0}; // Coordinates of the center of the map {double,double} linedistance = {0.0050,0.0050}; // Distance between subsequent rows double stepsize = 0.0050; // Distance between subsequent points in the raster line int nlines_tot = 1; // Number of rows in the map; int npoints = 10; // Number of points per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string throw = ""; // Identifier for chop throw, empty is standard {int,int,int,int,int,int,int,int,int,int,int,int,int} timing = {4,10,4,21,1,1800,0,10,1,1,1,50,0}; // full timing parameter list int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles }{ // Assign values int pointing = timing{1}; int loadlength = timing{3}; int holdlength = timing{4}; int n_loadinterval = timing{7}; int initlength = timing{11}; int dangling = timing{12}; // Create variables for telescope command string ib = GetBoresight(band,lo_freq,true); // A change of ra-dec depending on naifid may be needed double ra = mapcenter{0}; double dec = mapcenter{1}; double patt = AngleFromVector(linedistance); patt = RotateRight(patt); // Pattern angle and throw of the chopper direction // The nodding angle should always be parallel to the chopper double[] chopper = GetSkyChopThrow(band,lo_freq,throw); double nodlength = chopper[0]; double pattnod = chopper[1]; nodlength = max(nodlength * 3600.0,2.0); // Map always in sky coordinates, // (nod is always in instrument coordinates by default) bool fixed = true; // Map parameters double rowstep = 0.5 / 3600.0; double d1 = double(iceil(stepsize / rowstep)) * rowstep * 3600.0; double linestep = 0.5 / 3600.0; double d2 = AngleVectorLength(linedistance); d2 = double(iceil(d2 / linestep)) * linestep * 3600.0; // Exception for the "impossible" case of spacings below 2arcsec d1 = max(d1,2.0); d2 = max(d2,2.0); // Treat load slew either as load or as hold depending on n_cycles if(n_loadinterval > n_cycles) { int nload = 0; int nhold = n_loadinterval / n_cycles; // no hold if period too long if(nhold > npoints * nlines_tot) { nhold = 0; } } else { nload = n_loadinterval; nhold = 0; } // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(pointing < 10) { SError("Pointing phase length too short. Increase the number of integrations."); } if(nodlength > 960.0) { IError("Nodding length too long. Choose a smaller chop throw."); } if(d1 > 480.0) { IError("Raster point spacing too coarse. Increase the sampling."); } if(d2 > 480.0) { IError("Raster line spacing too coarse. Increase the sampling."); } // repetition at multiple frequencies not yet implemented: int trep = 0; int n_repeat = 1; // parameters for OFF position - not used int koff = 0; int toff = 0; double raoff = 0.0; double decoff = 0.0; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,fixed,patt,0.0,0.0,npoints,nlines_tot,d1,d2,pointing,holdlength,nhold,pattnod,nodlength,n_cycles,koff,toff,raoff,decoff,n_repeat,trep,loadlength,nload}; } ///////////////////////////////////////////////////////////////// // Spectral scan in load-chop without OFF calibration // {string,double,double}[] procedure HifiSScanProcLoadChopNoRefSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // inherit from fs-noref mode // spectral scans always use the full bandwidth for reference bool narrowReference = false; {string,double,double}[] retvalues = HifiPointProcLoadChopNoRefSequencerInit(naifid,ra,dec,band,reffreq,effResolution,narrowReference,hr1,hr2,wb1,wb2,data_time,n_cycles,load_interval,docommands); retvalues[1] = {"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}; return retvalues; } //////////////////////////////////// // OTF observing mode // // Return time and noise levels {string,double,double}[] procedure HifiMappingProcOTFSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,5]; // chunk size given by the data rates and optimum speed int n_int_on = 1 in [1,1800]; // Supersamplingfactor int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int main_phase = iceil(0.3 * allan_time_lores); // How many lines could we do at most using datalimit? int n_linesperscan_guess = main_phase / datalimit + 1; n_linesperscan_guess = imax(n_linesperscan_guess * n_linesperscan_guess / npoints,1); // restrict the scan size if(nlines == 1 && n_linesperscan_guess > 1) { n_linesperscan_guess = 2; } else { n_linesperscan_guess = IMultiple(n_linesperscan_guess,nlines); n_linesperscan_guess = imin(n_linesperscan_guess,nlines); } int n_linesperscan_range = 1 - n_linesperscan_guess; if(n_linesperscan_range == 0) { n_linesperscan_range = 1; } double n_pointsperscan = double(n_linesperscan * npoints); // Compute back int int_time_guess = imax(main_phase / iceil(sqrt(n_pointsperscan)),datalimit); int data_time_guess = imin(5,int_time_guess); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_int_on_guess = imax(int_time_guess / data_time_guess,1); int n_int_on_range = 1 - n_int_on_guess; if(n_int_on_range == 0) { n_int_on_range = 1; } // OFF integration int n_switch_off_guess = ifloor(double(n_int_on) * 0.67 * sqrt(n_pointsperscan)); int n_switch_off_range = n_switch_off_guess / 3; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_linesperscan",double(n_linesperscan_guess),double(n_linesperscan_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)}]; return retvalues; } // Routine to compute the periodic HK parameters {string,int,double,double,double,double} procedure PeriodicHKParms { string speed = "normal" in ["fast","normal","slow"]; // Select HK rate }{ // HK rate value accoring to IFSI/OBS/MA/2005-001 int ratevalue = ifloor(dlookup("datarates",speed + "_hkrate_value","value")); // Assign // No exception handling here - CUS internals only string[] allowedvalues = ["1_pkt_per_5_s","1_pkt_per_10_s","1_pkt_per_s","1_pkt_per_3_s","1_pkt_per_4_s"]; int[] allowedperiods = [5,10,1,3,4]; string hk_string = allowedvalues[ratevalue]; int hk_period = allowedperiods[ratevalue]; // Get all relevant parameters int pmax = ifloor(dlookup("datarates","maxbuspackets","value")); int per_hkpackets = iceil(dlookup("datarates","periodic_hkpackets","value")); int per_hksize = iceil(dlookup("datarates","periodic_hksize","value")); int ess_hkpackets = iceil(dlookup("datarates","ess_hkpackets","value")); int ess_hksize = iceil(dlookup("datarates","ess_hksize","value")); int osize = ifloor(dlookup("datarates","packetoverhead","value")); // Compute rates double per_packetrate = double(per_hkpackets) / double(hk_period); double per_datarate = double(per_hkpackets * (per_hksize + osize)) / double(hk_period); double ess_packetrate = double(ess_hkpackets) / double(hk_period); double ess_datarate = double(ess_hkpackets * (ess_hksize + osize)) / double(hk_period); // return everything return {hk_string,hk_period,per_packetrate,per_datarate,ess_packetrate,ess_datarate}; } // Interpolate differential load chop Allan time and exponent double[] procedure InterpolateSpecLChopAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ // subband is not used yet double[] allan = CalibrationReader("loadchop_Allan",["spec_Allan_time","spec_Allan_exp","spec_binning_exp"],band,lo_freq); return allan; } procedure SError { string errormessage = "Bad sequence parameters."; // Error message }{ string fullmessage = "Invalid sequence parameter combination:
" + errormessage + "
Rerun the sequencer to obtain a valid observing request."; error(fullmessage); } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for a // Spectral Scan DBS observing mode // // We currently assume that each nodding motion is related to an // instrument calibration. This may be an efficiency limitation if // more calibration measurements are needed. Then the loop sequence // should be changed. // // This implementation assumes that the whole scan can be performed // with a single pointing command. If the system temperature varies // too much so that it cannot be compensated by a slight change of // the redundancy, the scan has to be split into several calls of this // mode. // {{int,int,int,int,int,int,int,int,int,bool,int,int,int},{int,double,double[],int[][],bool,double[],int,bool}} procedure SScanDBS_pre_timing { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_chop = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Create composite readout structure for backends {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First check the group length // The frequency group length is given by n_freq_point. // It is derived in the sequencer using // GetFNoCalibLength(band,ref_freq); // For n_cycles>1 it has to be unity, everything else is rejected // We rely on the sequencer to determine the best group length if(n_cycles > 1 && n_freq_point > 1) { SError("Only frequency group length 1 allowed for cycle numbers > 1."); } // Get frequency grid characteristic parameters {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq_low,lo_freq_up,redundancy,0.0,n_freq_point); double reffreq = fqparms{1}; double[] freqgrid = fqparms{2}; int[][] grouporder = fqparms{3}; // Process tuning level grid double[][] levelgrid = GetSScanLevelGrid(band,wbs1,wbs2,freqgrid,fqparms{0},grouporder); {bool,double[]} targets = TargetLevels(band,reffreq,levelgrid); bool retuning = targets{0}; double[] targetgrid = targets{1}; string reftarget = ""; if(retuning) { reftarget = "sscan_normal"; } // Collect all frequency information in a tuple {int,double,double[],int[][],bool,double[],int,bool} spectralparms = {fqparms{0},reffreq,freqgrid,grouporder,retuning,targetgrid,fqparms{4},fqparms{5}}; ////////////////////////////////////////////////////////////////////// // Get timing within the normal DBS observations // Compute load integration time int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); loadlength = loadlength + readoutdead; int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int jitterdead = GetMaxTimeJitter(band,reffreq); // Integration time per frequency and pointing int inttime = 2 * n_chop * data_time; int readouttime = data_time; // Duration of initial set up // Staying at the same frequency makes no sense here. // First frequency point double runningfreq = freqgrid[grouporder[0][0]]; // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,runningfreq,false); } initlength = initlength + loadlength; // Tuning delays int bigtunestep = duration(HIFIRetuneFreq(band,reffreq,reftarget)); // Correct for variation within the band int tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq); bigtunestep = bigtunestep + tunediff; if(n_freq_point > 1) { int smallstep = duration(HIFIChangeFreq(band,reffreq)); } else { smallstep = bigtunestep; } // For double phases I can use the added jitterdead in both phases for tune int halftunestep = (bigtunestep - jitterdead + 1) / 2; // Check load_interval allowance int scan_time = 2 * inttime + bigtunestep; if(scan_time > load_spacing) { SError("Load interval of " + load_interval + "s is exceeded by " + n_chop + " chop cycles."); } // Rough estimate of the pointing time to issue a representative // telescope command if(n_cycles > 1) { // How often do I have to perform a load slew int n_loadinterval = imax(load_interval / scan_time,1); // fit with n_cycles n_loadinterval = imin(n_loadinterval,n_cycles); n_loadinterval = IMultiple(n_loadinterval,n_cycles); // Pointing time int pointing = inttime + jitterdead; } else { n_loadinterval = 1; pointing = n_freq_point * inttime + (n_freq_point - 1) * smallstep + halftunestep + jitterdead; } int n_bchop = n_chop; // recompute load length during slews in case of short integrations // This regime must be maintained in the post_timing if(n_loadinterval <= 1) { loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,false,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; } // No dangling needed in this mode - we stop halftunelength before telescope int dangling = 0; bool end_load = false; // Return all the times needed for telescope call and post_timing processing return {{inttime,pointing,readouttime,loadlength,jitterdead,load_spacing,bigtunestep,n_loadinterval,n_bchop,end_load,smallstep,initlength,dangling},spectralparms}; } ///////////////////////////////////////////////////////////////// // Fast-chop spectral scan observing modes // {string,double,double}[] procedure HifiSScanProcFastDBSSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time / 2); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of DBS modes // Get the drift parameters to compute the drift noise // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double} phaselengths = DBSPhaseLengths(band,reffreq,effResolution,continuumDetection,narrowReference); // Compute derived quantities // Top down approach here int main_phase = iceil(phaselengths{0}); // Arbitrary selection of data_time int data_time_guess = 20; // remaining part for n_switch int n_switch_on_guess = main_phase / (n_freq_point_guess * data_time_guess) + 1; data_time_guess = main_phase / (n_freq_point_guess * n_switch_on_guess); // Check with data rate {int,double[]} dataparms = DataTaking(backendreadoutparms,8); int datalimit = 2 * dataparms{0}; if(data_time_guess < datalimit) { data_time_guess = datalimit; n_switch_on_guess = 1; } int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Chop phase length double phase_min = min(max(phaselengths{1},0.15),1.5); int n_int_on_guess = ifloor(double(data_time_guess) / (2.0 * phase_min)); int n_int_on_range = -n_int_on_guess / 2; if(n_int_on_range == 0) { n_int_on_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } // Get maximum delay needed for backend readout after SlowChopSpectroscopy int procedure SlowChopReadoutDelay { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Currently the delay applies independent from the spectrometer selection // if (backendreadoutparms{2}{0} || backendreadoutparms{3}{0}) { double[] dead = CalibrationReader("slowchopreadout",["slowchopreadout"],band,lo_freq); // } return iceil(dead[0]); } // Interpolate differential total power sky chop Allan time and exponent double[] procedure InterpolateTpChopAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ // subband is not used yet double[] allan = CalibrationReader("chop_Allan",["tp_Allan_time","tp_Allan_exp","tp_binning_exp"],band,lo_freq); return allan; } ///////////////////////////////////////////////////////////////// // Procedure to compute the detailed frequency grid for a // spectral scan {int,double,double[],int[][],int,bool} procedure MakeFreqGrid { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy double freq_throw = 0.0; // Frequency throw in case of FSW observations int grouplen = 1; // Number of frequency steps before pointing to second phase }{ // First check validity of frequencies CheckLOFrequencies(band,lo_freq_low,lo_freq_up); // Rigid check - not needed as scan will be reduced below // CheckLOFrequencies(band,lo_freq_low+min(freq_throw,0.0), // lo_freq_up+max(freq_throw,0.0)); // Get frequency grid characteristic parameters // Perform the check for the redundancy {double,int,double} gfref = GetFReference(band,lo_freq_low,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // Check that redundancy is allowed if(redundancy * increment != stdredun) { IError("The selected redundancy is no factor of " + stdredun + "!"); } // Perform check for allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int maxgrouplen = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); if(grouplen > maxgrouplen) { SError("The group size exceeds the frequency range possible without recalibration."); } // We set up the frequency grid in four steps // Separate edges and main part of spectral scan {int,double,double} edgeampl = GetEdgeEnhance(redundancy,band); int highredun = edgeampl{0}; int inchigh = stdredun / highredun; // Check that redundancy is allowed if(highredun * inchigh != stdredun) { IError("The required redundancy at the band edges cannot be satisfied!"); } double nu1 = lo_freq_low; double nu2 = lo_freq_low + edgeampl{1}; double nu3 = lo_freq_up - edgeampl{1}; double nu4 = lo_freq_up; // Check for very small scans if(nu2 > nu4) { nu2 = nu4; } if(nu3 < nu1) { nu3 = nu1; } // Get frequency grid indices {int,int} ffindex = GetFScanBoundaries(band,freq_throw); {int,int} gfindex_lo = GetFIndex(band,nu1,nu2); {int,int} gfindex_up = GetFIndex(band,nu3,nu4); int index1 = gfindex_lo{0}; int index2 = gfindex_lo{1}; int index3 = gfindex_up{0}; int index4 = gfindex_up{1}; // Make frequency grid self-consistent and monotoneous // Shift if needed by frequency switch if(index1 < ffindex{0}) { index2 = index2 + ffindex{0} - index1; index1 = ffindex{0}; } if(index4 > ffindex{1}) { index3 = index3 + ffindex{1} - index4; index4 = ffindex{1}; } // Check again for very small scans if(index2 > index4) { index2 = index4; } if(index3 < index1) { index3 = index1; } // // lower frequency end with high redundancy int nstep1 = (index2 - index1 + inchigh - 1) / inchigh; index2 = index1 + nstep1 * inchigh; // Check again that we do not exceed the band boundary in this step if(index2 > ffindex{1}) { // No check here, we cannot exceed both boundaries index1 = index1 - index2 + ffindex{1}; index2 = ffindex{1}; } // upper end with high redundancy // Exception handling for small scans int nstep3 = imax((index4 - imax(index3,index2) + inchigh - 1) / inchigh - 1,0); index3 = index4 - nstep3 * inchigh; // main part inbetween, edges already covered int nstep2 = imax((index3 - index2 + increment - 1) / increment - 1,0); int index5 = index2 + nstep2 * increment; // Number of points int nfreq = nstep1 + nstep2 + nstep3 + 1; // Now we can construct the frequency grid from the index markers double[] freqgrid = GetFScanPoints(band,index1,index2,inchigh); // Consistency check if(nstep1 + 1 != length(freqgrid)) { CError("Frequency grid error. First frequency steps inconsistent."); } double[] addpoints = GetFScanPoints(band,index2,index5,increment); // Consistency check if(nstep2 + 1 != length(addpoints)) { CError("Frequency grid error. Main frequency steps inconsistent."); } for(int ia2 = 1 .. nstep2) { freqgrid[nstep1 + ia2] = addpoints[ia2]; } addpoints = GetFScanPoints(band,index3,index4,inchigh); // Consistency check if(nstep3 + 1 != length(addpoints)) { CError("Frequency grid error. Last frequency steps inconsistent."); } if(nstep3 > 0) { for(int ia3 = 1 .. nstep3) { freqgrid[nstep1 + nstep2 + ia3] = addpoints[ia3]; } } // Initial definition of the frequency grid finished // Check vs. system temperature and attenuators - modify if required double tsys = InterpolateTsys(band,reffreq); double[] tsysarray = GetAllTsys(band,freqgrid); // Search for frequencies with too high tsys double tsyslimit = GetTsysVariationLimit(band,reffreq); tsyslimit = tsys * tsyslimit; bool[] hightsys = []; int nadd = 0; for(int in1 = 0 .. nfreq - 1) { hightsys[in1] = tsysarray[in1] > tsyslimit; if(hightsys[in1]) { nadd = nadd + 1; } } // Add some integrations to make the total number of points an // integer multiple of the group size int groupnumber = (nfreq + nadd + grouplen - 1) / grouplen; int nrest = groupnumber * grouplen - nfreq - nadd; // add integrations at points of highest system temperature not yet covered for(int ng = 1 .. nrest) { int curmax = -1; double tsysmax = 0.0; for(int in2 = 0 .. nfreq - 1) { // dont duplicate points which are already duplicated if(!hightsys[in2]) { // search for maximum if(tsysarray[in2] > tsysmax) { curmax = in2; tsysmax = tsysarray[in2]; } } } if(curmax >= 0) { // Add point hightsys[curmax] = true; } else { // Giving up string obscure = "Perfect observation! You managed to set up the " + "observation that will explain life, the universe, and everything. " + "However, as this would drastically lower future research funding, " + "the observation is rejected. "; // Throw message IError(obscure + "Please, increase frequency interval or reduce redundancy!"); } } // Actually expand frequency grid int newindex = 0; double[] newgrid = []; for(int in3 = 0 .. nfreq - 1) { newgrid[newindex] = freqgrid[in3]; newindex = newindex + 1; if(hightsys[in3]) { newgrid[newindex] = freqgrid[in3]; newindex = newindex + 1; } } // Consistency check nfreq = nfreq + nadd + nrest; if(nfreq != length(newgrid)) { CError("Frequency grid error. Expanded frequency grid inconsistent."); } // Information about frequency grid message("Actually covered frequency range: " + newgrid[0] / 1000.0 + " - " + newgrid[nfreq - 1] / 1000.0 + "GHz.
"); // Summary message message("Total number of LO settings: " + nfreq + "
"); // Create index for frequency stepping within a group int[][] grouporder = GetFrequencyGroupSteps(grouplen); // Check for very small scans if(lo_freq_up - lo_freq_low >= edgeampl{1} + edgeampl{2}) { bool dsb = true; int nfreq_if = redundancy; } else { if(lo_freq_up - lo_freq_low >= edgeampl{2}) { dsb = false; nfreq_if = highredun; } else { dsb = false; nfreq_if = nfreq; } } // Final sanity check CheckSpectralScanRange(band,reffreq,newgrid[0],newgrid[nfreq - 1]); // Return all frequency parameters return {groupnumber,reffreq,newgrid,grouporder,nfreq_if,dsb}; } //Set LOU to nominal, procedure //Set LOU in nominal mode with no channel selected procedure Set_LO_Nominal_proc_aot { }{ {double,string}[] result = ConfigurationReader("name_delays",["set_to_nominal_delay"],"0",0.0); int set_to_nominal_delay = iround(result[0]{0}); // Hifi_HIFI_HL_Normal($BBID); delay(set_to_nominal_delay); // } // Compute minimum nod time in a nod used for loads // Used only in case of scansize > 1 int procedure GetMinLoadNod { int[] telescopetimes = [300,180,20,0,21,0,4,10,10,10]; int scansize = 2; // Number of points measured in one scan int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles int n_loadinterval = 1; // Number of nods to include loads }{ // Use telescope return parameters int numpoints = telescopetimes[6]; // Scan return field int n_scans = numpoints / (2 * scansize); int n_loadnods = n_scans / n_loadinterval; int longslew = 180; // guarantee that all nods are shorter for(int i1 = 0 .. n_loadnods - 1) { int theindex = 6 + scansize + i1 * (n_loadinterval * 2 * scansize); longslew = imin(longslew,telescopetimes[theindex]); } return longslew; } {int,double,double,double,double,double} obs HifiPointModeFastDBS { string modeName = "dbs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-FastChop-DBS",{data_time,0,n_switch_on,n_int_on,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = FastDBS_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} post_timing = DBS_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; bool end_load = post_timing{1}{9}; int shiftlength = post_timing{1}{10}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastDBS_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,n_loadinterval,end_load,final_load,startobs,telescopetimes,loadlength,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = FastDBS_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBS_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_seq * n_int_on * (n_load + 1),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Get maximum commanding time jitter which has to be added as margin int procedure GetMaxTimeJitter { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("timejitter",["timejitter"],band,lo_freq); return iceil(dead[0]); } // Get the standard chop angle difference from calibration file double[] procedure GetSkyChopThrow { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency string throw = ""; // Identifier for chop throw, empty is standard }{ string lstring = throw + "length"; string astring = throw + "angle"; double[] nodpatt = CalibrationReader("skychopthrow",[lstring,astring],band,lo_freq); // We chop now from plusZ tu minusZ, i.e. in negative direction double patt = nodpatt[1] + 180.0; // restrict to allowed range patt = (patt + 360.0) % 360.0; return [nodpatt[0],patt]; } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command inherited from DBS mode //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure FastDBS_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_seq = 1; // Number of continuous data transfer cycles int n_load = 0; // additional load measurements in one pointing phase int n_loadinterval = 10; // number of nods before a load measurement bool end_load = false; // Need for load after each pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration int shiftlength = 10; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int load_datatime = GetStdLoadReadout(band,lo_freq); // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time / 2); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; int[] choppars = [2 * n_int,0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load) { HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Second phase in first nod position // occurs for even cycle numbers runintostate = false; if(state[2] % 2 == 0) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 7) { // second nod position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i2 = 1 .. n_load) { HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // First phase in second nod position // occurs for odd cycle numbers runintostate = false; if(state[2] % 2 == 1) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement // ( Does not occur if end_load is set) LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } // Slow chop integration at source position OFF-ON-ON-OFF... block HIFISlowChopOnIntegration HIFI 6031 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3left","chop_M3right"],rates); } //////////////////////////////////////// // Procedure to calculate the pre timing // {int,int,int,int,int,int,int,int,int,bool,int,int,int} procedure FastDBS_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 1 in [1,1800]; // number of data transfer cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int load_datatime = GetStdLoadReadout(band,lo_freq); // It should be investigated wehther we can use fast-chop on loads as well // Perform consistency checks int single_data = data_time / 2; // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,single_data); // Check chopper frequency CheckFastChopFrequency(band,lo_freq,data_time,n_int,n_data); // Telescope-instrument communication jitter int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int readouttime = data_time; int inttime = data_time * n_data; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms)); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // For double phases I can use the added jitterdead in both phases for load int halfloadlength = (loadlength - jitterdead + 1) / 2; // Compare load interval and nodding interval // This determines the order of the loops int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); if(load_spacing < data_time) { SError("Load period shorter than backend readout period."); } int n_load = inttime / load_spacing; if(load_spacing > 2 * inttime) { int n_seq = n_data; bool end_load = false; int pointing = inttime + jitterdead; int shiftlength = 0; } else { n_seq = n_data / (n_load + 1); if(n_seq < 1) { SError("Transfer cycle too long relative to load period."); } end_load = true; inttime = n_seq * (n_load + 1) * data_time; pointing = inttime + halfloadlength + n_load * loadlength + jitterdead; shiftlength = halfloadlength; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // Compute the overall cycle length // First estimate of the load interval int n_loadinterval = imax(load_interval / (2 * pointing),1); // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {inttime,pointing,readouttime,loadlength,jitterdead,load_spacing,n_load,n_loadinterval,n_seq,end_load,shiftlength,initlength,dangling}; } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command is inherited from load chop //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure FSwitchNoRef_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval limited by the data rates int n_per_on = 1; // number of half load-sky-sky-load cycles on ON int n_load_on = 0; // additional load measurements in ON pointing phase bool end_load_on = false; // Need for load after ON pointing phase int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,0]; // Timing of observation from telescope int loadlength = 50; // Load duration }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // ON integration HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load_on) { HIFIFSwitchOnIntegration(data_time,n_per_on,band,lo_freq,rates); // Perform load calibration delay(readoutdead); DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureFSwitchIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFSwitchOnIntegration(data_time,n_per_on,band,lo_freq,rates); } if(state[0] == 5) { delay(readoutdead); if(end_load_on) { // Perform final load measurement DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms); } HIFICloseObs(); } } } // get HRS efficiency double procedure GetHrsEfficiency { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] resol = CalibrationReader("backendresolution",["hrs_efficiency"],band,lo_freq); return resol[0]; } {string,double,double}[] procedure HifiMappingModeDBSCrossSequencerInit { string modeName = "cross"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // inherit from dbs-raster mode {string,double,double}[] retvalues = HifiMappingProcDBSRasterSequencerInit(naifid,ra,dec,{0.0,double(npoints / 2) * stepsize},2,stepsize,npoints,band,lo_freq,effResolution,continuumDetection,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); return retvalues; } ///////////////////////////////////////////////////////////////// // Auxiliary routine to determine the two loop phase durations for all // DBS modes {double,double} procedure DBSPhaseLengths { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF }{ // Get the drift parameters to compute the drift noise if(continuumDetection) { double[] allanparms = InterpolateTpAllan(band,lo_freq,oneGHzReference); } else { allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); } // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Differential Allan variance if(continuumDetection) { allanparms = InterpolateTpChopAllan(band,lo_freq,oneGHzReference); } else { allanparms = InterpolateSpecChopAllan(band,lo_freq,oneGHzReference); } // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // phase lengths double main_phase = 0.3 * dallan_time_lores; double chop_phase = 0.3 * allan_time_lores; // Constrain by load period int loadper = LoadPeriod(band,lo_freq,effResolution{0}); main_phase = min(main_phase,0.4 * double(loadper)); return {main_phase,chop_phase}; } // Get main beam size for message double procedure GetTsysVariationLimit { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] fwhm = CalibrationReader("tsysvariation",["tsysvariation"],band,lo_freq); return fwhm[0]; } // get backend resolution and effective noise resolution double[] procedure GetBackendResolution { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency int res_mode = 0; // coding for the backend resolution mode }{ if(res_mode < 0 || res_mode > 3) { double[] resol = CalibrationReader("backendresolution",["wbs_resolution","wbs_fluct_ratio"],band,lo_freq); } if(res_mode == 0) { resol = CalibrationReader("backendresolution",["hrs_high_resolution","hrs_fluct_ratio"],band,lo_freq); } if(res_mode == 1) { resol = CalibrationReader("backendresolution",["hrs_normal_resolution","hrs_fluct_ratio"],band,lo_freq); } if(res_mode == 2) { resol = CalibrationReader("backendresolution",["hrs_low_resolution","hrs_fluct_ratio"],band,lo_freq); } if(res_mode == 3) { resol = CalibrationReader("backendresolution",["hrs_wide_resolution","hrs_fluct_ratio"],band,lo_freq); } return resol; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the DBS raster mode procedure JupiterDBSRaster_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_seq = 1; // Number of continuous chop cycles int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles int n_pointsperscan = 1; // Number of points measured before moving to the second pointing phase int n_loadinterval = 10; // number of nods before a load measurement int n_load = 0; // additional load measurements in one pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,0,10,20,21,0,0,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration bool iscross = false; // Whether we use a cross instead of a raster }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get all values from the telescope section int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Count phases by hand to allow simultaneous usage by Raster and Cross int iphase = 0; // There is no nod counter in the return values - count this by hand int inod = 0; // Do I have to make loads in short nods and subsequent holds? if(iscross) { bool holdforload = n_pointsperscan > 1; } else { holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles; } //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"jupiter"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; iphase = iphase + 1; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles // The use of n_load differs by 1 from the other observing modes here for(int i1 = 1 .. n_load - 1) { HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: // n_pointsperscan=1, n_loadinterval > n_cycles if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } // Update phase counter iphase = iphase + 1; } // Second pointing phase if(state[0] == 7) { // second nod position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); for(int i2 = 1 .. n_load - 1) { HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } // Update phase counter iphase = iphase + 1; } // Load nod if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } // Hold if(state[0] == 6) { // finished shift of instrument operations relative to pointing command runintostate = false; } // Final load if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } //////////////////////////////////// // Fast chop DBS raster observing mode - special version for Jupiter // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcJupiterFastDBSRaster { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-Jupiter-FastChop-DBS-Raster",{data_time,0,n_int_on,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer // Two changes relative to the normal DBS raster // 1) The longer load duration is enforced by zero resolution {double,double} loadResolution = {0.0,effResolution{1}}; // 2) I assume that the tuning duration does not depend on the tuning level // so that the normal pre_timing can be reused. {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(nlines,npoints,band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { JupiterFastDBSRaster_commanding(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Perform frequency-switch integration at ON position block HIFIFSwitchOnIntegration HIFI 6038 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_fswitch_proc_aot(data_time,n_cycle,band,lo_freq,rates); } ////////////////////////////////////////////////////////////////////////////// // routines from ILT not used in observing modes ////////////////////////////////////////////////////////////////////////////// //Configure LCU in nominal mode at frequency of interest procedure ConfigureLOUnominal { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz }{ LCU_config_nominal_proc_aot(band,lo_freq / 1000.0); } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure SScanChopNoRef_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int n_cycles = 1; // Number of chop cycles int freqsteps = 4; // Total number of frequencies bool fs = false; // whether frequency switch used double tscan = 10.0; // Total average duration of one scan double tdead = 0.05; // Average dead time in one chop cycle }{ // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); // Use DSB noise for long spctral scans if(dsb) { double idealnoiselsb = idealvalues{1} * idealvalues{1}; double idealnoiseusb = idealvalues{3} * idealvalues{3}; double idealnoise = idealnoiselsb * idealnoiseusb / (idealnoiselsb + idealnoiseusb); } else { idealnoise = idealvalues{1} * idealvalues{1}; } double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for range coverage double accumulation = double(freqsteps) / double(nfreq); idealnoise = idealnoise * accumulation; double efficiency = idealnoise / obsnoise; // Compute the actual integration time double inttime = (tscan - tdead) / 2.0; double posinttime = double(n_cycles) * 2.0 * inttime * double(freqsteps); double posofftime = 0.0; int instrumenttime = iceil(double(freqsteps) * tscan); // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,fs); } // Frequency switch procedure HIFI_Spectr_fswitch_proc_aot { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ // set data rates non_ess_hk_data_rate(rates[2] / 1024.0); data_rate(rates[0] / 1024.0); // Call command Hifi_HIFI_Spectr_freq_switch($BBID); delay(2 * n_cycle * data_time); // reset data rates non_ess_hk_data_rate(rates[1] / 1024.0); data_rate(0.0); } // Frequency of load measurements // This is no longer computed, but tabulated as it does not depend // on user parameters - deltanu is a dummy parameter int procedure LoadPeriod { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency double deltanu = 1.0; // maximum effective resolution of the calibrated data }{ // Get the stability parameters double[] allanparms = CalibrationReader("loaddiff_stability",["tp_stability_time"],band,lo_freq); int period = ifloor(allanparms[0]); return period; } //Retune HIFI for frequency switch - keep magnet and backends procedure HIFITuneFreqNoretuneFsw { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq_1 = 978200.0; //LO frequency for FSW1 phase double lo_freq_2 = 978300.0; //LO frequency for FSW2 phase }{ // Setting with no retune for first frequency, and store in FSW1 register LCU_config_nominal_noretune_block_aot(band,lo_freq_1 / 1000.0,true); // // Second frequency setup, and stored in FSW2 register LCU_config_nominal_noretune_block_aot(band,lo_freq_2 / 1000.0,true); // } //////////////////////////////////// // Fast chop DBS raster - cross observing mode // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcFastDBSCross { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the two raster lines int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-FastChop-DBS-Cross",{data_time,0,n_switch_on,n_int_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(2,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = custom_map_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSCross_post_timing(pre_timing,telescopetimes,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = custom_map_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int scansize = post_timing{1}{10}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastDBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,true); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,2,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Correct for double counting of central point // The central point is returned only double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; noisevalues{4} = noisevalues{4} / multiplier; // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Auxiliary routine to check for bad map sizes // procedure CheckReasonableLineNumber { int nlines = 1; // Number of OTF lines in a map bool isOtf = true; // whether this is an OTF of a raster map }{ // Give warning in case of "bad" map sizes // Here is a very bad place to make the test - it should rather go to HSPOT int divisors = 0; int[] divlist = [2,3,4,5]; for(int idiv = 0 .. 3) { if(nlines % divlist[idiv] == 0) { divisors = divisors + 1; } } if(nlines > 10 && divisors < 2 || nlines > 6 && divisors < 1) { if(isOtf) { message("Warning: The map contains " + nlines + " lines. " + "This cannot be split efficiently into equal scans of " + "multiple lines. Try to change your map size.
"); } else { message("Warning: The map contains " + nlines + " points. " + "This cannot be split efficiently into equal scans of " + "multiple points.Try to change your map size.
"); } } } //////////////////////////////////// // Error reporting functions - containing some standard text procedure CError { string errormessage = "Inconsistency detected."; // Error message }{ string fullmessage = "Internal HIFI observing mode error:
" + errormessage + "
Please, report this error together with the AOR file to the " + "Herschel Science Centre Helpdesk."; // To be replaced by a link to the SPR system when this can handle AOR files error(fullmessage); } ////////////////////////////////////////////////////////////////////////// // Auxiliary routine to guarantee matching of telescope API with // respect to map sizes and scan velocities // {double,double,int} procedure ValidMapSize { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} linedistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines_tot = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints_inp = 10 in [1,720]; // Number of data dumps per row int data_time = 4; // readout time }{ // Define maximum reduction - no reduction any more double eps = 1.0; // What is wanted double reqsize = stepsize * double(npoints_inp); // First evaluate valid step size double ratestep = 0.1 / 3600.0; double scanvelocity = stepsize / double(data_time); // Check for too low scanning speeds resulting in a discretization // error larger than half the step size if(scanvelocity < 2.0 * ratestep) { SError("Scan velocity too small for accurate map coverage."); } // Compute actual discretized rate double rate = double(iceil(scanvelocity * eps / ratestep)) * ratestep; double validstepsize = rate * double(data_time); // A message is the only feedback mechanism that we have here. double reldiff = (validstepsize - stepsize) * double(npoints_inp); if(abs(reldiff) > 0.5 * stepsize) { message("OTF readout is adjusted to occur every " + dformat(validstepsize * 3600.0,1) + "'' instead of the requested " + dformat(stepsize * 3600.0,1) + "''.
"); } // 2. step: Extend the npoints number to match the telescope API double rowmin = 20.0 / 3600.0; double rowstep = 5.0 / 3600.0; // Correct for possible 1s jitter, i.e. enlarge stripes int jitterdead = GetMaxTimeJitter(band,lo_freq); double step1s = validstepsize * double(jitterdead) / double(data_time); // Implementation assumes that rowmin is an integer multiple of rowstep if(reqsize > rowmin) { double fullrowlength = double(iceil((reqsize * eps + step1s) / rowstep)) * rowstep; } else { fullrowlength = rowmin; } int npoints = imax(ifloor((fullrowlength - step1s) / validstepsize),2); // Iterate on fullrowlength to avoid overheads double dumpsize = double(npoints) * validstepsize + step1s; if(dumpsize > rowmin) { fullrowlength = double(iceil(dumpsize / rowstep)) * rowstep; } else { fullrowlength = rowmin; } // Message reldiff = fullrowlength - step1s - reqsize; if(abs(reldiff) > 0.5 * stepsize) { message("The length of all OTF stripes is adjusted to cover " + dformat(double(npoints) * validstepsize * 3600.0,1) + "'' instead of the requested " + dformat(reqsize * 3600.0,1) + "''.
"); } // Granularity for d2 // This is duplicated from OTF_telescope double linestep = 0.5 / 3600.0; double d2_req = AngleVectorLength(linedistance); double d2 = double(iceil(d2_req * eps / linestep)) * linestep; // Exception for the "impossible" case of spacings below 2arcsec if(d2 > 0.0) { d2 = max(d2,2.0 / 3600.0); } // Message reldiff = (d2 - d2_req) * double(nlines_tot); if(abs(reldiff) > 0.5 * d2_req) { message("The OTF stripe distance is adjusted to " + dformat(d2 * 3600.0,1) + "'' instead of the requested " + dformat(d2_req * 3600.0,1) + "''.
"); } return {fullrowlength,rate,npoints}; } // Procedure to check whether fast chop frequency is high enough for // HRS internal integration and low enough for mechanical chopper constraints // procedure CheckFastChopFrequency { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int data_time = 10 in [4,128]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 2; // Integration time counter }{ // Get timing parameters {int,int,int,int,int,int,int,int,int,int,int,int,int} timing = FastConfigureSpectroscopyParams(data_time,n_int,n_data,band,lo_freq,true); int del_wbs = timing{5}; int t_acc_wbs = timing{6}; int t_acc_hrs = timing{7}; // Maximum phase length {double,string}[] result = ConfigurationReader("name_delays",["max_hrs_phase"],band,lo_freq); int max_hrs_phase = iround(result[0]{0}); // Minimum chop phase length int min_wbs_phase = GetMinChopPhaseLength(band,lo_freq); // Checks if(t_acc_wbs + del_wbs < min_wbs_phase) { SError("Chop phases too short for chopper mechanics. Reduce chop frequency."); } if(t_acc_hrs > max_hrs_phase) { SError("Chop phase length too long for HRS. Increase chop frequency."); } } // Get dead time for chopper motion on the sky double procedure GetLoadChopDeadTime { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("lchop_deadtime",["loadchop"],band,lo_freq); return dead[0]; } // messages giving gyro-calibration information procedure GCPMessages { int gcp_time = 15; // pointing time at GCP int gcp_period = 500; // period for visiting the GCP int tend = 0; // final decelleration time as indication for planet }{ // Constants hard coded int tend_fixed = 0; int critical = 0; int min_gcp_time = 15; int max_gcp_period = 2000; // close any previous messages message("

"); message("

Gyro-calibration

"); message("

"); // Actual messages if(gcp_time > critical) { if(tend > tend_fixed) { message("A-posteriori pointing improvement is not possible for " + "solar system objects."); } else { if(gcp_time >= min_gcp_time && gcp_period <= max_gcp_period) { message("A-posteriori relative pointing improvement can be obtained " + "from a gyro-calibration taking " + gcp_time + "s every " + gcp_period + "s."); } else { message("The AOR is not optimized for gyro-calibration."); message("It is not clear whether any a-posteriori relative " + "pointing improvement can be obtained from a " + "gyro-calibration taking " + gcp_time + "s every " + gcp_period + "s."); } } } else { message("No a-posteriori pointing improvement possible for this AOR."); } } ///////////////////////////////////////////////////////////////// // Second step of timing computation after telescope behaviour // is known - Spectral Scan frequency switch observing mode // {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double,double} procedure SScanDoubleChop_post_timing { {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing = {16,16,16,16,21,11,1800,32,2,2,0,0,false,false,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,20,1,21,0]; int grouplen = 1; // Number of frequencies to group into one cycle int groupnumber = 50; // Total umber of frequency groups int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency }{ // Get all values from the pre_timing section int on_inttime = pre_timing{0}; int off_inttime = pre_timing{1}; int on_pointing = pre_timing{2}; int off_pointing = pre_timing{3}; int loadlength = pre_timing{4}; int auxtunestep = pre_timing{5}; int load_spacing = pre_timing{6}; int n_loadinterval = pre_timing{7}; int n_chop_on = pre_timing{8}; int n_chop_off = pre_timing{9}; int data_time_on = pre_timing{10}; int data_time_off = pre_timing{11}; bool end_load_on = pre_timing{12}; bool end_load_off = pre_timing{13}; int initlength = pre_timing{14}; int dangling = pre_timing{15}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to OFF int longslew = telescopetimes[4]; // Actual slew time for load slew int pointwaittime = telescopetimes[3]; // Idle time between two phases int tend = telescopetimes[5]; // Final deceleration time ////////////////////////////////////////////////////////////////// // Now we start the actual computations // Pointwaittime is used for tuning // In all non-tuning cycles, pointwaittime acts like a longer slew slewtime = slewtime + pointwaittime; longslew = longslew + pointwaittime; // Half tune step has to be rounded up int halftunestep = (auxtunestep + 1) / 2; int effhalftunestep = (auxtunestep - pointwaittime + 1) / 2; int shiftlength = halftunestep - effhalftunestep; // Correct pointing times on_pointing = on_pointing - shiftlength; off_pointing = off_pointing - shiftlength; // Check group length limited by load_interval int scan_time = on_pointing + off_pointing + slewtime; if(scan_time > load_spacing + slewtime && grouplen > 1) { SError("Frequency group length too large for load interval."); } // Compute load cycles and average times if(n_cycles > 1) { // How often do I have to perform a load slew // Never switch between short load and long load here if(n_loadinterval > 1) { int old_n_loadinterval = n_loadinterval; n_loadinterval = imax((load_spacing + slewtime) / scan_time,1); // fit with n_cycles n_loadinterval = imin(n_loadinterval,n_cycles); n_loadinterval = IMultiple(n_loadinterval,n_cycles); if(n_loadinterval <= 1) { n_loadinterval = old_n_loadinterval; } } // Determine need for final load measurement double rest = double(n_cycles * groupnumber % n_loadinterval) + 0.5; bool final_load = rest > 0.5001 * double(n_loadinterval); // part of integrations is added when not needed for tuning int n_add_on = effhalftunestep / (2 * data_time_on); int n_long_on = n_chop_on + n_add_on; int n_add_off = effhalftunestep / (2 * data_time_off); int n_long_off = n_chop_off + n_add_off; // Average times for noise estimate int longint_on = n_long_on * 2 * data_time_on; int longint_off = n_long_off * 2 * data_time_on; int numlong_on = 2 * (n_cycles / 2); double effchop_on = double(numlong_on * n_long_on + (n_cycles * grouplen - numlong_on) * n_chop_on) / double(grouplen * n_cycles); int numlong_off = 2 * ((n_cycles - 1) / 2); double effchop_off = double(numlong_off * n_long_off + (n_cycles - numlong_off) * n_chop_off) / double(n_cycles); int loadpercycle = n_cycles / n_loadinterval; double cycletime = double(on_pointing + off_pointing) + double(loadpercycle * longslew + (n_cycles - loadpercycle) * slewtime) / double(n_cycles); double tscan = (cycletime * double(n_cycles) - double(2 * halftunestep)) / double(n_cycles); // retuning does not increase drift } else { // Determine need for final load measurement if(groupnumber % 2 == 0) { rest = double(off_pointing); } else { rest = double(on_pointing); } final_load = rest > 0.5001 * double(load_spacing); // All cycles have the same length n_long_on = n_chop_on; n_long_off = n_chop_off; // Average times for noise estimate effchop_on = double(n_chop_on); effchop_off = double(n_chop_off); cycletime = double(on_pointing + off_pointing + longslew); tscan = cycletime - double(2 * effhalftunestep); } ////////////////////////////////////////////////////////////////////// // Compute total duration initlength = initlength - effhalftunestep; shiftlength = effhalftunestep; // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int totaltime = iround(cycletime * double(groupnumber * n_cycles)); // Add dangling load time - this should not occur, just for consistency if(final_load) { dangling = loadlength - shiftlength; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute total duration, remove pointwaittime for last slew totaltime = totaltime + dangling - pointwaittime + tend; // show gyro-propagation messages int pointcycle = on_pointing + off_pointing + longslew; GCPMessages(off_pointing,2 * pointcycle,tend); // Return all the times needed in the observing mode modules return {totaltime,{on_inttime,off_inttime,on_pointing,off_pointing,loadlength,shiftlength,load_spacing,n_loadinterval,n_long_on,n_long_off,1,1,final_load,final_load,initlength,dangling},effchop_on,effchop_off,tscan}; } double procedure HotColdRelaxTime { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency bool wbsused = true; // whether one of the WBS' is used }{ // Dead time given purely by the chopper double relaxtime = GetHotColdDeadTime(band,lo_freq); // Add WBS relaxation if this is used if(wbsused) { // Get the Bragg cell time constant double[] bragg = CalibrationReader("bragg_cell",["bragg_relaxtime"],band,lo_freq); double t_bragg = bragg[0]; // Get the other involved temperatures double tsys = InterpolateTsys(band,lo_freq); {double,double} tloads = LoadTemperatures(band,lo_freq); // Compute involved level difference double hotlevel = tsys + tloads{0}; double coldlevel = tsys + tloads{1}; double difference = (hotlevel - coldlevel) / hotlevel; relaxtime = max(relaxtime,t_bragg * difference); } return relaxtime; } // Get minimum integration time per phase for fast-chop int procedure GetMinChopPhaseLength { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] freq = CalibrationReader("chopfreq",["maxchopfreq"],band,lo_freq); double phaselength = 1000.0 / (2.0 * freq[0]); return iceil(phaselength); } // Routines for calibration data handling ///////////////////////////////////////////////////////////////// // Generic calibration file reader. This is called by all routines // using calibration parameters. The same approach is used for fixed, // band-dependent and LO frequency dependent quantities. Thus we // can add more calibration information as we obtain it. // double[] procedure CalibrationReader { string topicname = "tsys"; // Name of entry in master file string[] objectnames = ["tsys_h"]; // Names of calibration objects to be read string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ // first step: read master file string calibfile = slookup("calibration_masterfile",topicname,"filename"); int dep = ilookup("calibration_masterfile",topicname,"dependence"); int readnum = length(objectnames); double[] retvalues = []; if(dep == 0) { // Quantity is constant // Read from single file by name for(int i = 1 .. readnum) { retvalues[i - 1] = dlookup(calibfile,objectnames[i - 1],"value"); } } else { if(dep == 1) { // Quantity is band dependent // directly read from file looking up the band for(int k = 1 .. readnum) { retvalues[k - 1] = dlookup(calibfile,band,objectnames[k - 1]); } } else { // Quantity is band and frequency dependent // second step step: band look up, get name of responsible data file string actualfile = slookup(calibfile,band,"filename"); // Now read interpolated value from the data base for(int j = 1 .. readnum) { retvalues[j - 1] = interpolate(actualfile,objectnames[j - 1],lo_freq); } } } return retvalues; } //Chopper rotation procedure. Reduced version without overshooting treatment // Always one step procedure RotateChopper { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency string chop_target = "chop_cold"; //Targetted chopper position }{ {bool,double,double} chopparms = GetChopVoltages(band,lo_freq,chop_target,chop_target); bool isPrime = chopparms{0}; // Call command if(isPrime) { Hifi_HIFI_P_Chopper_Rot($BBID,chopparms{1}); } else { Hifi_HIFI_R_Chopper_Rot($BBID,chopparms{1}); } // No delays should be required here } // Interpolate coupling of the instrument for the selected frequency double procedure InterpolateCoupling { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] eta = CalibrationReader("efficiency",["eta_mb"],band,lo_freq); return eta[0]; } // General version used in most observingmodes procedure LoadMeasurement { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency double deltanu = 1.0; // minimum effective resolution of the calibrated data int data_time = 4; // time between subsequent data readouts {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Call generic version with fixed parameters SScanLoadMeasurement(band,lo_freq,lo_freq,true,deltanu,data_time,backendreadoutparms); } {string,double,double}[] procedure HifiMappingModeLoadChopOTFNoRefSequencerInit { string modeName = "load-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int data_time_guess = imin(imax(iceil(0.3 * allan_time_lores),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // n_switch limited by load_interval - 2 lines should be possible int n_switch_on_guess = load_interval / (4 * npoints * data_time_guess); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Contruct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)}]; return retvalues; } bool procedure IntIsContained { int x = 1; // search string int[] lot = [0]; // array to be searched }{ int nlen = length(lot); bool found = false; for(int i = 0 .. nlen - 1) { if(x == lot[i]) { found = true; } } return found; } // perform peak-up correction block HifiPeakupCorrection HIFI 6822 { }{ // Perform correction Hifi_HIFI_correction_AOCS($BBID); delay(1); } ///////////////////////////////////////////////////////////////////////////// // The actual commanding procedures // total power procedure HIFI_Spectr_tp_proc_aot { int n_int = 1; // Integration time counter int data_time = 4; // Integration time between two data readouts double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ // set data rates non_ess_hk_data_rate(rates[2] / 1024.0); data_rate(rates[0] / 1024.0); // Call command Hifi_HIFI_Spectr_total_power($BBID); delay(n_int * data_time); // reset data rates non_ess_hk_data_rate(rates[1] / 1024.0); data_rate(0.0); } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure SScanChopNoRef_noisecomputer { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference LO frequency in scan center int nfreq = 4; // Number of frequency points per IF bool dsb = true; // Both sidebands covered {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz int n_cycles = 1; // Number of map coverages bool fs = false; // whether frequency switch used double tscan = 60.0; // Total average duration of one scan double tdead = 10.0; // Average dead time in one slew }{ // spectral scans always use the full bandwidth for reference bool oneGHzReference = false; // Call position switch noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,reffreq,eff_resolution,oneGHzReference,n_cycles,tscan,tdead); // Correct for multiple frequencies and signal in both phases in case of FSW if(fs) { double multiplier = sqrt(0.5 / double(nfreq)); } else { multiplier = sqrt(1.0 / double(nfreq)); } noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; // Check for double sideband coverage if(dsb) { // Combine LSB-USB noise // In spectral scans we have only a combined noise temperature for both // sidebands, so that the USB/LSB separation is not used double[] gssb = InterpolateGssb(band,reffreq); double usbnoise_lores = noisevalues{0} / sqrt(1.0 + gssb[1] / gssb[0] * (gssb[1] / gssb[0])); double usbnoise_hires = noisevalues{1} / sqrt(1.0 + gssb[1] / gssb[0] * (gssb[1] / gssb[0])); double lsbnoise_lores = usbnoise_lores; double lsbnoise_hires = usbnoise_hires; } else { // Get single sideband noise equivalent usbnoise_lores = noisevalues{0}; usbnoise_hires = noisevalues{1}; lsbnoise_lores = noisevalues{2}; lsbnoise_hires = noisevalues{3}; } // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noisevalues{4}}; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of DBS-raster cross observing mode {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} procedure DBSCross_post_timing { {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = {4,10,4,21,1,1800,0,10,1,1,1,50,0}; // full timing parameter list int[] telescopetimes = [300,180,20,0,21,0,2,10]; int npoints = 10; // Number of points per row int n_chop = 2; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800; // load period = f(band,lo_freq,eff_resolution{1}) bool fastchop = false; // whether fast-chop is used instead of slow-chop }{ // Get all values from the pre_timing section int inttime = pre_timing{0}; int pointing = pre_timing{1}; int readouttime = pre_timing{2}; int loadlength = pre_timing{3}; int jitterdead = pre_timing{4}; int load_spacing = pre_timing{5}; int n_load = pre_timing{6}; int n_loadinterval = pre_timing{7}; int n_seq = pre_timing{8}; int n_scans = pre_timing{9}; int scansize = pre_timing{10}; int initlength = pre_timing{11}; int dangling = pre_timing{12}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int longslew = telescopetimes[4]; // Actual slew time for load slew int tend = telescopetimes[5]; // Final deceleration time /////////////////////// // Long computation for scansize > 1 to obtain all slew durations {int,int,int} sumslewtimes = GetAllCrossSlewTimes(telescopetimes,scansize,n_cycles); int tinscandead = sumslewtimes{0}; int toutscandead = sumslewtimes{1}; int shortmove = sumslewtimes{2}; // Total number of scans int n_tot = n_scans * n_cycles; // Compute total duration of measurement and average scan length int totalscantime = n_tot * (2 * pointing * scansize) + tinscandead; // approximate scan time for load comparison int scan_time = iceil(double(totalscantime) / double(2 * n_tot)); if(load_spacing > 2 * scan_time) { n_seq = n_chop; pointing = inttime + jitterdead; bool end_load = false; } else { // It could happen that the slew extends the scan too much - catch if(scansize > 1) { SError("Number of points in one scan too large for load period."); } n_load = n_load + 1; n_seq = n_chop / n_load; // adjust pointing time to include load measurements int loadappend = imax(loadlength - shortmove,0); end_load = true; // Computation for slow-chop or fast-chop if(fastchop) { inttime = n_seq * n_load * readouttime; } else { inttime = 2 * n_seq * n_load * readouttime; } pointing = inttime + loadappend + (n_load - 1) * loadlength + jitterdead; } totalscantime = n_tot * (2 * pointing * scansize) + tinscandead + toutscandead; scan_time = iceil(double(totalscantime) / double(2 * n_tot)); // compute the load interval in case of short scan_time n_loadinterval = imax((load_interval - loadlength + longslew) / (2 * scan_time),1); // Special treatment for nodding_IN_raster due to limitations in API // Split into loads per point or per multiple points if(scansize == 1) { int nodtime = tinscandead / n_tot; if(n_loadinterval > n_cycles) { n_loadinterval = n_cycles * (n_loadinterval / n_cycles); n_loadinterval = imin(n_loadinterval,n_tot); // Translate load waiting time into a hold after the point int holdlength = imax(loadlength - nodtime,0); int loadadded = holdlength; int n_long = n_tot / n_loadinterval; } else { // Nodding in raster with loads per point holdlength = 0; loadadded = longslew - nodtime; // compensate counter reset int dangling_period = n_cycles % n_loadinterval; while((dangling_period + n_loadinterval) * 2 * scan_time > load_interval - loadlength + longslew) { n_loadinterval = n_loadinterval - 1; dangling_period = n_cycles % n_loadinterval; } // Consistency check if(n_loadinterval < 1) { CError("Too short load period computed."); } n_long = n_scans * (n_cycles / n_loadinterval); } } else { // Treatment for nodding_OF_raster int minnod = GetMinLoadNod(telescopetimes,scansize,n_cycles,n_loadinterval); holdlength = imax(loadlength - minnod,0); loadadded = holdlength; n_long = n_tot / n_loadinterval; } // Compute total duration of measurement, correct for load nods totalscantime = n_tot * (2 * pointing * scansize) + tinscandead + n_long * loadadded; // Average dead and scan time for drift estimate double tscan = double(totalscantime) / double(n_tot); double tdead = tscan - double(2 * inttime * scansize); // Count integration times of other points of one nod as dead time // Other points in the second nod are excluded from the scan double othertime = double((scansize - 1) * inttime); tdead = tdead + othertime; // Reduce scan time by the other points in the second nod phase tscan = tscan - othertime; // Determine need for final load measurement double rest = double(n_tot % n_loadinterval) + 0.5; bool final_load = rest > 0.5001 * double(n_loadinterval); // Compute total duration // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int totaltime = totalscantime + toutscandead; // Add dangling load time if not included in pointing // they are mutually exclusive, otherwise the readoutdelay applies if(final_load) { dangling = loadlength; } if(end_load) { dangling = loadlength - loadappend; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); totaltime = totaltime + dangling + tend; // show gyro-propagation messages // no gyro-propagation for custom_map GCPMessages(0,totalscantime / n_cycles,tend); // Return all the times needed in the observing mode modules return {totaltime,{inttime,pointing,readouttime,loadlength,holdlength,load_spacing,n_load,n_loadinterval,n_seq,n_scans,scansize,initlength,dangling},final_load,tscan,tdead}; } // Get dead time for chopper motion double procedure GetSkyChopDeadTime { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] dead = CalibrationReader("chop_deadtime",["skychop"],band,lo_freq); return dead[0]; } // building block to initialize load calibration measurement // and compute main parameters {int,int,bool} block HIFICalInit HIFI 6008 { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency double deltanu = 1.0; // minimum effective resolution of the calibrated data int data_time = 4; // time between subsequent data readouts }{ // The minimum integration time is given by data_time // However, we introduce an upper limit of 6s here (covers 24bit mode) int used_datatime = imin(data_time,6); // Check whether frequent retuning is needed double[] allan = CalibrationReader("loaddiff_stability",["instable"],band,lo_freq); bool retuning = allan[0] > 0.0; // Compute integration time int min_int_time = LoadIntegrationTime(band,lo_freq,deltanu); if(retuning) { int n_inttime = 2 * iceil(0.5 * double(min_int_time) / double(used_datatime)); } else { n_inttime = 2 * iceil(double(min_int_time) / double(used_datatime)); } // return parameters return {used_datatime,n_inttime,retuning}; } // LCU switch-off, block block LCU_switch_off_block_aot HIFI 6631 { }{ {double,string}[] result = ConfigurationReader("name_delays",["switch_off_delay"],"0",0.0); int switch_off_delay = iround(result[0]{0}); // //Send command: this is the effective switch-off Hifi_HIFI_Conf_nom_LCU_ch0($BBID); // delay(switch_off_delay); // //Set heater to their stby value: should not depend on band HL_heater_proc_aot("1a","stby"); } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // double procedure PositionSwitch_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,5]; // data dump interval limited by the data rates int n_int = 3 in [2,1800]; // number of data dumps for integration per phase double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute parameters for the instrument timing {double,double} tinst = GetInstDeadSlowChop(data_time,n_int,"tp",band,lo_freq,backendreadoutparms); // total dead time in one cycle double tinst_dead = double(data_time * n_int) - tinst{0}; // Total dead time per cycle double tdead_tot = tdead + 2.0 * tinst_dead; return tdead_tot; } //Set HIFI to standby I - lasers are forced to Off. HBB stays ON obs HifiEngSetIntoStandby_I { }{ // pre_timing {int,int} pre_timing = Eng_pre_timing(); int initlength = pre_timing{0}; int closelength = pre_timing{1}; int mainduration = duration(HifiIntoStandby_I()); // telescope command int[] ts = no_pointing(true,initlength,closelength,mainduration); }{ // Instrument commanding - use state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 2) { // Initialization HIFIInitObs(); HIFISetHK("fast",true); } if(state[0] == 3) { // ON integration HifiIntoStandby_I(); } if(state[0] == 5) { HIFISetHK("normal",true); HIFICloseObs(); } } } //////////////////////////////////// // Fast chop DBS raster observing mode - Engineering version with half throw // // The timing is defined as WBS timing, the HRS takes more data during // the WBS read out, but this is ignored in the computations here. // // Return time and noise levels {int,double,double,double,double,double} obs HifiEngHalfThrowFastDBSRaster { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-FastChop-DBS-Raster",{data_time,0,n_int_on,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(nlines,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"half",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { HalfFastDBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } /////////////////////////////////////////////////////////////////// // Procedure to compute detailed post timing for the version of the // load-chop and frequency-switch modes with baseline measurement // {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},int,bool,double,double} procedure DoubleChop_post_timing { {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing = {16,16,16,16,21,11,1800,32,2,2,0,0,false,false,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,20,1,21,0]; int n_cycles = 1; // Number of half OFF-ON-ON-OFF calibration cycles }{ // Get all values from the pre_timing section int on_inttime = pre_timing{0}; int off_inttime = pre_timing{1}; int on_pointing = pre_timing{2}; int off_pointing = pre_timing{3}; int loadlength = pre_timing{4}; int jitterdead = pre_timing{5}; int load_spacing = pre_timing{6}; int n_loadinterval = pre_timing{7}; int n_per_on = pre_timing{8}; int n_per_off = pre_timing{9}; int n_load_on = pre_timing{10}; int n_load_off = pre_timing{11}; bool end_load_on = pre_timing{12}; bool end_load_off = pre_timing{13}; int initlength = pre_timing{14}; int dangling = pre_timing{15}; // Use all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to OFF int pointwaittime = telescopetimes[3]; // Idle time between two phases int longslew = telescopetimes[4]; // Actual slew time for load slew int tend = telescopetimes[5]; // Final deceleration time // If load is performed between the cycles use pointwaittime for load int halfloadlength = (loadlength - jitterdead + 1) / 2; int effhalfloadlength = (loadlength - jitterdead - pointwaittime + 1) / 2; if(end_load_on) { on_pointing = on_pointing - (halfloadlength - effhalfloadlength); int shiftlength_on = effhalfloadlength; } else { shiftlength_on = 0; } if(end_load_off) { off_pointing = off_pointing - (halfloadlength - effhalfloadlength); int shiftlength_off = effhalfloadlength; } else { shiftlength_off = 0; } // treat remaining pointwaittime like an additional slew dead time in cycles slewtime = slewtime + pointwaittime; longslew = longslew + pointwaittime; // Now we can compute the true scan time int scan_time = on_pointing + off_pointing + slewtime; // Finally I can compute the load interval n_loadinterval = imax((load_spacing + slewtime) / scan_time,1); // Exception handling for very uneven phases if(end_load_on || end_load_off) { n_loadinterval = 1; } // Variables for the noise computer // Compute duration of measurement and average scan length // Compute total dead time in one pointing cycle including load overhead int scan_time_long = on_pointing + off_pointing + longslew; int n_long = n_cycles / n_loadinterval; // Determine need for final load measurement double rest = double(n_cycles % n_loadinterval) + 0.5; bool final_load = rest > 0.5001 * double(n_loadinterval); int looplength = (n_cycles - n_long) * scan_time + n_long * scan_time_long; double tscan = double(looplength) / double(n_cycles); // Get pointing dead time, instrument dead time is added later double tdead = tscan - double(off_inttime + on_inttime); int initshiftlength = shiftlength_off; // Check the last pointing cycle, repeated on the telescope procedure if(n_cycles % 2 == 0) { int lastshiftlength = shiftlength_off; } else { lastshiftlength = shiftlength_on; } // Add dangling load time if(lastshiftlength > 0) { dangling = loadlength - lastshiftlength; } if(final_load) { dangling = loadlength; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute total duration initlength = initlength - initshiftlength; // The initial time is no longer contained in the total time // Compute total duration, remove pointwaittime for last slew int totaltime = looplength + dangling - pointwaittime + tend; // show gyro-propagation messages GCPMessages(off_pointing,2 * scan_time_long,tend); // Return all the times needed in the telescope and instrument modules return {totaltime,{on_inttime,off_inttime,on_pointing,off_pointing,loadlength,jitterdead,load_spacing,n_loadinterval,n_per_on,n_per_off,n_load_on,n_load_off,end_load_on,end_load_off,initlength,dangling},initshiftlength,final_load,tscan,tdead}; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure OTFmap_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int n_supersample = 1; // Supersamplingfactor int n_linesperscan = 1; // Number of lines between two OFFs int n_intoff = 3; // Number of data dumps for the OFF integration time int n_pp = 10; // Number of data dumps per line double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Dead time in OFF {double,double} tinst = GetInstDeadSlowChop(data_time,n_intoff,"tp",band,lo_freq,backendreadoutparms); // dead time within OFF double tdeadint = double(data_time * n_intoff) - tinst{0}; // total dead time from OFF double tdead_tot = tdead + tdeadint; double tintoff = tinst{0}; // Dead time in one line tinst = GetInstDeadSlowChop(data_time,n_pp,"tp",band,lo_freq,backendreadoutparms); // Dead time for each line tdeadint = double(data_time * n_pp) - tinst{0}; tdead_tot = tdead_tot + double(n_linesperscan) * tdeadint; double tintpoint = tinst{0} / double(n_pp) * double(n_supersample); // Return total dead time and actual integration times return {tdead_tot,tintpoint,tintoff}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure LoadChopNoRef_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval limited by the data rates int n_per_on = 2; // number of half load-sky-sky-load cycles on ON int n_load_on = 0; // additional load measurements in ON pointing phase bool end_load_on = false; // Need for load after ON pointing phase int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,0]; // Timing of observation from telescope int loadlength = 21; // Load duration }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // ON integration HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load_on) { HIFILoadChopOnIntegration(data_time,n_per_on,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureLoadChopIntegration(data_time,n_per_on,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFILoadChopOnIntegration(data_time,n_per_on,band,lo_freq,rates); } if(state[0] == 5) { delay(readoutdead); if(end_load_on) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } HIFICloseObs(); } } } ///////////////////////////////////////////////////////////////// // Get limiting frequencies {double,double} procedure GetBandLimits { string band = "4a"; // HIFI band }{ // read master file string calibfile = slookup("frequencystep_masterfile",band,"tablefile"); double[] allfpoints = dcolumn(calibfile,"stepfrequency"); // get table size int iindex1 = length(allfpoints); double firstlo = allfpoints[1]; double lastlo = allfpoints[iindex1 - 2]; return {firstlo,lastlo}; } // Compute effective fluctuation bandwidth determining the // radiometric noise from the selected resolution {double,double} procedure EffectiveResolution { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Selected min./max. goal resolution of calibrated data bool resolutionMhz = true; //whether resolution is given in MHz or in km/s bool wbs1used = true; // WBS1 to be used bool wbs2used = true; // WBS2 to be used {bool,int} hrs1 = {true,1}; // {HRS1 to be used, resolution} {bool,int} hrs2 = {true,1}; // {HRS2 to be used, resolution} }{ // translate to Mhz is required double lightspeed = 300000.0; // km/s if(resolutionMhz) { double resol_hi = effResolution{0}; double resol_lo = effResolution{1}; } else { resol_hi = effResolution{0} * lo_freq / lightspeed; resol_lo = effResolution{1} * lo_freq / lightspeed; } // compute fluctuation bandwidth from selected resolution // 1. physical resolutions used // build up list of available resolutions double[] physres_list = [0.0]; double[] fluctratio_list = [0.0]; bool[] ishrs_list = [false]; int n_resol = 0; // WBS if(wbs1used || wbs2used) { double[] res = GetBackendResolution(band,lo_freq,-1); physres_list[n_resol] = res[0]; fluctratio_list[n_resol] = res[1]; ishrs_list[n_resol] = false; n_resol = n_resol + 1; } // resolution order of HRS's if(hrs1{0} && hrs2{0}) { int lores = imax(hrs1{1},hrs2{1}); int hires = imin(hrs1{1},hrs2{1}); if(hires != lores) { res = GetBackendResolution(band,lo_freq,lores); physres_list[n_resol] = res[0]; fluctratio_list[n_resol] = res[1]; ishrs_list[n_resol] = true; n_resol = n_resol + 1; res = GetBackendResolution(band,lo_freq,hires); physres_list[n_resol] = res[0]; fluctratio_list[n_resol] = res[1]; ishrs_list[n_resol] = true; n_resol = n_resol + 1; } else { res = GetBackendResolution(band,lo_freq,lores); physres_list[n_resol] = res[0]; fluctratio_list[n_resol] = res[1]; ishrs_list[n_resol] = true; n_resol = n_resol + 1; } } else { if(hrs1{0}) { res = GetBackendResolution(band,lo_freq,hrs1{1}); physres_list[n_resol] = res[0]; fluctratio_list[n_resol] = res[1]; ishrs_list[n_resol] = true; n_resol = n_resol + 1; } if(hrs2{0}) { res = GetBackendResolution(band,lo_freq,hrs2{1}); physres_list[n_resol] = res[0]; fluctratio_list[n_resol] = res[1]; ishrs_list[n_resol] = true; n_resol = n_resol + 1; } } // Compare with desired resolutions double physres_lo = physres_list[0]; double fluctratio_lo = fluctratio_list[0]; bool ishrs_lo = ishrs_list[0]; double physres_hi = physres_list[0]; double fluctratio_hi = fluctratio_list[0]; bool ishrs_hi = ishrs_list[0]; // go from lowest resolution to highest // get parameters of backend just covering the goal for(int iresol = 1 .. n_resol - 1) { if(resol_hi < physres_list[iresol - 1]) { physres_hi = physres_list[iresol]; fluctratio_hi = fluctratio_list[iresol]; ishrs_hi = ishrs_list[iresol]; } if(resol_lo < physres_list[iresol - 1]) { physres_lo = physres_list[iresol]; fluctratio_lo = fluctratio_list[iresol]; ishrs_lo = ishrs_list[iresol]; } } // Consistency check if(resol_hi < physres_list[n_resol - 1]) { IError("The requested goal resolution cannot be achieved with the" + " selected backend settings. Increase the goal resolution" + " minimum or change the spectrometer settings."); } // Translate into fluctuation bandwidths double effresol_lo = resol_lo + physres_lo * (fluctratio_lo - 1.0); double effresol_hi = resol_hi + physres_hi * (fluctratio_hi - 1.0); // correct for finite HRS efficiency - reduce noise bandwidth double hrseffic = GetHrsEfficiency(band,lo_freq); if(ishrs_hi) { effresol_hi = effresol_hi * (hrseffic * hrseffic); } if(ishrs_lo) { effresol_lo = effresol_lo * (hrseffic * hrseffic); } // return result return {effresol_hi,effresol_lo}; } // Produce array of LO frequencies to be used in frequency clusters double[] procedure GetClusterFrequencies { double lo_freq = 978200.0; // LO frequency in MHz int groupsize = 3; // Number of frequencies in a cluster double freqstep = 120.0; // step size in a frequency cluster }{ // Use the same order as within spectral scan groups int[][] grouporder = GetFrequencyGroupSteps(groupsize); double[] freqs = []; for(int i = 0 .. groupsize - 1) { freqs[i] = lo_freq + freqstep * double(grouporder[1][i] - groupsize / 2); } return freqs; } //////////////////////////////////// // Fast chop DBS raster observing mode // // The timing is defined as WBS timing, the HRS takes more data during // the WBS read out, but this is ignored in the computations here. // // Combination of four modules implementing the new structure // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcFastDBSRaster { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-FastChop-DBS-Raster",{data_time,0,n_switch_on,n_int_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = FastDBSRaster_pre_timing(nlines,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,true); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FastDBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = FastDBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * n_int_on * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Configuration for fast-chop integration int[] block HIFIConfigureFastChopIntegration HIFI 6040 { int data_time = 4; // Integration time between two data readouts int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_seq = 1; // Number of continuous data transfer cycles string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Call procedure doing the work {int,int} fchop = FastConfigureSpectroscopy(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Return data rates for command return [fchop{0},fchop{1}]; } ///////////////////////////////////////////////////////////////// // get reference frequency, resolution, redundancy {double,int,double} procedure GetFReference { string band = "4a"; // HIFI band double lo_freq1 = 978200.0 in [480000.0,1950000.0]; // LO frequency double lo_freq2 = 979600.0 in [480000.0,1950000.0]; // LO frequency }{ // first step: read master file double referencefreq = ComputeReferenceFreq(band,lo_freq1,lo_freq2); int redundancy = ilookup("frequencystep_masterfile",band,"redundancy"); double stdstep = dlookup("frequencystep_masterfile",band,"stdstep"); return {referencefreq,redundancy,stdstep}; } // Check whether the input frequencies are allowed procedure CheckLOFrequencies { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz }{ {double,double} bandlimits = GetBandLimits(band); if(lo_freq_low < bandlimits{0} || lo_freq_up < lo_freq_low || lo_freq_up > bandlimits{1}) { IError("Frequencies fall outside of the selected LO band."); } } ///////////////////////////////////////////////////////////////////////////// // The tuning blocks // // Initial tuning of the instrument procedure TuneHIFI { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1parms = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets,subbands used} {bool,int,double[],bool[]} hrs2parms = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets,subbands used} bool wbs1parms = true; // WBS1 parameter =used bool wbs2parms = true; // WBS2 parameter =used string level = "normal"; // Name of target level }{ // Switch to high HK rate HIFISetHK("fast",true); ConfigureFPU(band,lo_freq,true); ConfigureBackend(band,lo_freq,hrs1parms,hrs2parms); HIFITune(band,lo_freq,hrs1parms{0},hrs2parms{0},wbs1parms,wbs2parms,level); // Switch to standard HK rate HIFISetHK("normal",true); } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for the mode // {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} procedure PositionSwitch_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,5]; // data dump interval limited by the data rates int n_int = 3 in [2,1800]; // number of data dumps for integration per phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); // Compute parameters for the instrument timing int jitterdead = GetMaxTimeJitter(band,lo_freq); int inttime = n_int * data_time; // Resulting integer integration time int pointing = inttime + jitterdead; // Pointing time // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; int halfloadlength = (loadlength - jitterdead + 1) / 2; int load_spacing = CheckedLoadSpacing(load_interval - loadlength,2 * inttime); // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // Compute the load period // First estimate of the load interval int n_loadinterval = imax(load_interval / (2 * pointing),1); // Dangling load not known yet at this point bool final_load = false; int dangling = readoutdead; // pseudo parameters which are notneeded here, but used for a // unified treatment of all modes using the same pointing command int n_seq = 1; int n_load = 0; // Return all the times needed for telescope call and post_timing processing return {inttime,inttime,pointing,pointing,loadlength,halfloadlength,load_spacing,n_loadinterval,n_seq,n_seq,n_load,n_load,final_load,final_load,initlength,dangling}; } //////////////////////////////////// // Configuration routines /////////////////////////////////// //Generic procedure to configure the FPU using the adequate instrument side procedure HIFI_Configure_FCU_proc_aot { int band_nb = 0; // HF_CPR_MXBAND int diplex_h_ctrl_mode = 227; // HF_CV1_DPFPP1 double volt_H_FIF_1 = 0.075; // HF_CH2_FIF1_Drain_V double curr_H_FIF_1 = 0.5; // HF_CH2_FIF1_Drain_C double volt_H_FIF_2 = 0.075; // HF_CH2_FIF2_Drain_V double curr_H_FIF_2 = 0.5; // HF_CH2_FIF2_Drain_C double volt_H_SIF_1 = 0.075; // HF_CH2_SIF1_Drain_V double curr_H_SIF_1 = 0.5; // HF_CH2_SIF1_Drain_C double volt_H_SIF_2 = 0.075; // HF_CH2_SIF2_Drain_V double curr_H_SIF_2 = 0.5; // HF_CH2_SIF2_Drain_C double volt_H_SIF_3 = 0.075; // HF_CH2_SIF3_Drain_V double curr_H_SIF_3 = 0.5; // HF_CH2_SIF3_Drain_C int diplex_v_ctrl_mode = 227; // HF_CV1_DPFPP1 double volt_V_FIF_1 = 0.075; // HF_CV2_FIF1_Drain_V double curr_V_FIF_1 = 0.5; // HF_CV2_FIF1_Drain_C double volt_V_FIF_2 = 0.075; // HF_CV2_FIF2_Drain_V double curr_V_FIF_2 = 0.5; // HF_CV2_FIF2_Drain_C double volt_V_SIF_1 = 0.075; // HF_CV2_SIF1_Drain_V double curr_V_SIF_1 = 0.5; // HF_CV2_SIF1_Drain_C double volt_V_SIF_2 = 0.075; // HF_CV2_SIF2_Drain_V double curr_V_SIF_2 = 0.5; // HF_CV2_SIF2_Drain_C double volt_V_SIF_3 = 0.075; // HF_CV2_SIF3_Drain_V double curr_V_SIF_3 = 0.5; // HF_CV2_SIF3_Drain_C string chop_sine_s = "ON" in ["OFF","ON"]; // HF_CPR_CH_SINE_S string chop_loop = "CLOSE" in ["CLOSE","OPEN"]; // HF_CPR_CH_LOOP_S int chop_G1 = 0; // HF_CPR_CHFPG1 int chop_G2 = 0; // HF_CPR_CHFPG2 int chop_Z1 = 0; // HF_CPR_CHFPZ1 int chop_Z2 = 0; // HF_CPR_CHFPZ2 int chop_P2 = 0; // HF_CPR_CHFPP2 double calibcurrent = 0.0; // HF_CPR_Cal_Heater_C double bias_H = 0.0; // HF_CH1_MXBIAS_V double magnetcurrent_H = 0.0; // HF_CH1_MX_MG_C double bias_V = 0.0; // HF_CV1_MXBIAS_V double magnetcurrent_V = 0.0; // HF_CV1_MX_MG_C double chopper = -4.0 in [-8.88,8.5]; // HF_CPR_Chopper_Rot double diplex_H = 0.0; // HF_CH1_DPACT_C double diplex_V = 0.0; // HF_CV1_DPACT_C }{ //check prime or redundant keyword {double,string}[] result_d = ConfigurationReader("name_chopper",["prime_or_redundant"],"0",0.0); if(result_d[0]{1} == "prime") { Hifi_HIFI_P_Configure_FCU($BBID,band_nb,diplex_h_ctrl_mode,volt_H_FIF_1,curr_H_FIF_1,volt_H_FIF_2,curr_H_FIF_2,volt_H_SIF_1,curr_H_SIF_1,volt_H_SIF_2,curr_H_SIF_2,volt_H_SIF_3,curr_H_SIF_3,diplex_v_ctrl_mode,volt_V_FIF_1,curr_V_FIF_1,volt_V_FIF_2,curr_V_FIF_2,volt_V_SIF_1,curr_V_SIF_1,volt_V_SIF_2,curr_V_SIF_2,volt_V_SIF_3,curr_V_SIF_3,chop_sine_s,chop_loop,chop_G1,chop_G2,chop_Z1,chop_Z2,chop_P2,calibcurrent,bias_H,magnetcurrent_H,bias_V,magnetcurrent_V,chopper,diplex_H,diplex_V); } else { Hifi_HIFI_R_Configure_FCU($BBID,band_nb,diplex_h_ctrl_mode,volt_H_FIF_1,curr_H_FIF_1,volt_H_FIF_2,curr_H_FIF_2,volt_H_SIF_1,curr_H_SIF_1,volt_H_SIF_2,curr_H_SIF_2,volt_H_SIF_3,curr_H_SIF_3,diplex_v_ctrl_mode,volt_V_FIF_1,curr_V_FIF_1,volt_V_FIF_2,curr_V_FIF_2,volt_V_SIF_1,curr_V_SIF_1,volt_V_SIF_2,curr_V_SIF_2,volt_V_SIF_3,curr_V_SIF_3,chop_sine_s,chop_loop,chop_G1,chop_G2,chop_Z1,chop_Z2,chop_P2,calibcurrent,bias_H,magnetcurrent_H,bias_V,magnetcurrent_V,chopper,diplex_H,diplex_V); } // } ///////////////////////////////////////////////////////////////// // Get all frequency points in interval double[] procedure GetFScanPoints { string band = "4a"; // HIFI band int firstindex = 1; // Index of first frequency point int lastindex = 2; // Index of last frequency point int increment = 1; // Index increment }{ // first step: read master file string calibfile = slookup("frequencystep_masterfile",band,"tablefile"); double[] allfpoints = dcolumn(calibfile,"lo_frequency"); // Initialize field int nstep = (lastindex - firstindex + 2 * increment - 1) / increment; double[] fpoints = []; // Loop for reading for(int i = 0 .. nstep - 1) { int counter = firstindex + i * increment; fpoints[i] = allfpoints[counter]; } return fpoints; } ///////////////////////////////////////////////////////////////// // Slow chop dual beam switch observing mode // // Implemented as procedure returning time and noise levels for HSPOT {string,double,double}[] procedure HifiPointProcDBSSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_guess = imax(iceil(phaselengths{0} / (2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)}]; return retvalues; } //Tune HIFI at frequency of interest for 2 frequencies (FSW) procedure HIFITuneFsw { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq_1 = 978200.0; //LO frequency for FSW1 phase double lo_freq_2 = 978300.0; //LO frequency for FSW2 phase bool hrs1used = true; // HRS1 parameter =used bool hrs2used = true; // HRS2 parameter bool wbs1used = true; // WBS1 parameter =used bool wbs2used = true; // WBS2 parameter string target_name = "normal"; // Name of target level }{ // //LO power tuning: could use either H or V polar {double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq_1); double x = result[0]{0}; string tuningbackend = "H"; if(iround(x) == 2) { tuningbackend = "V"; } else { tuningbackend = "H"; } // All tuning for first frequency, and store in FSW1 register double lo_freq_setting = 0.5 * (lo_freq_1 / 1000.0 + lo_freq_2 / 1000.0); LO_tuning_block_aot(band,lo_freq_1 / 1000.0,lo_freq_setting,tuningbackend,true,true,true); // //Magnet tuning: could use either HRS or WBS. Not done for bands6-7 if(band != "6a" && band != "6b" && band != "7a" && band != "7b") { // Currently only the HRS is used string magnettuningbackend = "HRS"; Magnet_tuning_block_aot(band,lo_freq_1 / 1000.0,magnettuningbackend); } // //Spectrometer attenuator tuning on HBB if(wbs1used || wbs2used) { WBS_attenuators_block(band,lo_freq_1 / 1000.0,target_name,false); } if(hrs1used || hrs2used) { HRS_tune_block_aot(band); } // Second frequency setup, and stored in FSW2 register LO_tuning_block_aot(band,lo_freq_2 / 1000.0,lo_freq_setting,tuningbackend,false,true,true); // } //////////////////////////////////// // OTF load-chop observing mode // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcLoadChopOTF { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-LoadChop-OTF",{data_time,data_time_off,0,n_switch_on,n_switch_off,n_linesperscan,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,int,int,int,int} pre_timing = OTFLoadChop_pre_timing(nlines,npoints_used,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_with_off_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int},double,double} post_timing = OTFmap_post_timing(pre_timing,telescopetimes,data_time,n_linesperscan,n_cycles,load_interval); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_with_off_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int n_pp = post_timing{1}{0}; int n_scans = post_timing{1}{1}; int off_inttime = post_timing{1}{2}; int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{5}; double tscan = post_timing{2}; double tdead = post_timing{3}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFLoadChop_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,npoints_used * n_switch_on,n_switch_off,nlines * n_cycles,n_linesperscan,n_loadinterval,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double,double,double} tact = OTFDoubleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,n_pp,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = OTFLoadChop_noisecomputer(band,lo_freq,effResolution,oneGHzReference,nlines,data_time,n_switch_on,n_linesperscan,off_inttime,n_cycles,tscan,tact); // Evaluate performance OTFDoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on,n_switch_off,n_scans,n_cycles,false,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // DBS raster observing mode - special version for Jupiter // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcJupiterDBSRaster { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-Jupiter-DBS-Raster",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer // Two changes relative to the normal DBS raster // 1) The longer load duration is enforced by zero resolution {double,double} loadResolution = {0.0,effResolution{1}}; // 2) I assume that the tuning duration does not depend on the tuning level // so that the normal pre_timing can be reused. {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(nlines,npoints,band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { JupiterDBSRaster_commanding(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Compute the length of an angular vector, derived from AngularDistance double procedure AngleVectorLength { {double,double} vector = {0.0,0.0}; // vector }{ double pideg = 3.14159265 / 180.0; double dist = acos(cos(vector{0} * pideg) * cos(vector{1} * pideg)) / pideg; return dist; } // Continuous HIFI integration with given backend settings at source block HIFIContOnIntegration HIFI 6022 { int n_int = 1; // Integration time counter int data_time = 4; // Integration time between two data readouts double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_tp_proc_aot(n_int,data_time,rates); } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of DBS-raster observing mode {int,int,int,int,int,int,int,int,int,int,int,int,int} procedure FastDBSRaster_pre_timing { int nlines_tot = 1 in [1,100]; // Number of rows in the map int npoints = 10 in [2,100]; // Number of points per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_data = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int readouttime = data_time; int load_datatime = GetStdLoadReadout(band,lo_freq); // It should be investigated wehther we can use fast-chop on loads as well // Perform consistency checks int single_data = data_time / 2; // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,single_data); // Check chopper frequency CheckFastChopFrequency(band,lo_freq,data_time,n_int,n_data); // Is the map size an integer multiple of the scan size? CheckReasonableLineNumber(nlines_tot * npoints,false); int scansize = n_pointsperscan; if(scansize > nlines_tot * npoints) { SError("Scan size exceeds the total map size."); } if(nlines_tot * npoints % scansize != 0) { SError("Map size is no integer multiple of the scan size."); } int n_scans = nlines_tot * npoints / scansize; // Compute parameters for the instrument timing int jitterdead = GetMaxTimeJitter(band,lo_freq); int inttime = readouttime * n_data; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms)); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // compute the load interval in case of short scan_time int scan_time = inttime * scansize; int n_loadinterval = imax(load_interval / scan_time,1); // Special treatment for nodding_raster due to limitations in API // Split into loads per point or per multiple points if(scansize == 1 && n_loadinterval > n_cycles) { n_loadinterval = n_cycles * (n_loadinterval / n_cycles); } n_loadinterval = imin(n_loadinterval,n_cycles * n_scans); // Compare load interval and nodding interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); if(load_spacing < readouttime) { SError("Load period shorter than backend readout period."); } // load measurements within a single point integration int n_load = inttime / load_spacing; if(n_load >= 1 && scansize > 1) { SError("Number of points in one scan too large for load period."); } // Rough estimate of the pointing time - this is corrected // after the evaluation of the telescope command if(load_spacing > 2 * scan_time) { int n_seq = n_data; int pointing = inttime + jitterdead; } else { // It is possible that a single point is short enough, but a scan // too long. Then everything is reduced to a single point. scansize = 1; n_scans = nlines_tot * npoints; n_seq = n_data / (n_load + 1); inttime = n_seq * (n_load + 1) * readouttime; pointing = inttime + (n_load + 1) * loadlength + jitterdead; } // dangling time given by readout dead time int dangling = readoutdead; int holdlength = jitterdead; // Return all the times needed for telescope call and post_timing processing return {inttime,pointing,readouttime,loadlength,holdlength,load_spacing,n_load,n_loadinterval,n_seq,n_scans,scansize,initlength,dangling}; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure SingleChopNoRef_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int n_chop_on = 1; // number of half load-sky-sky-load cycles on ON bool fs = false; // whether frequency switch used double tscan = 10.0; // Total average duration of one scan double tdead = 0.05; // Average dead time in one chop cycle }{ // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; double efficiency = idealnoise / obsnoise; // Compute the actual integration time double inttime = (tscan - tdead) / 2.0; double posinttime = double(n_chop_on) * 2.0 * inttime; double posofftime = 0.0; // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,fs); } ////////////////////////////////////////////////////////////////////// // Determine data readout period and corresponding data rate {int,double[]} procedure DataTaking { {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 int data_time = 4; // Integration time between two data readouts }{ // Definitions - read from calibration file: // WBS // 16 bit format for short integrations int wbs16bitlimit = 5; if(data_time <= wbs16bitlimit) { int wbit = ifloor(dlookup("datarates","wbsbitnormal","value")); int nchannelwbs = ifloor(dlookup("datarates","nchannelwbsnormal","value")); } else { // 24 bit mode wbit = ifloor(dlookup("datarates","wbsbithigh","value")); nchannelwbs = ifloor(dlookup("datarates","nchannelwbshigh","value")); } // HRS=24 bit int hbit = ifloor(dlookup("datarates","hrsbit","value")); int nchannelhrs = ifloor(dlookup("datarates","nchannelhrs","value")); // Maximum data rate int pmax = ifloor(dlookup("datarates","maxbuspackets","value")); int osize = ifloor(dlookup("datarates","packetoverhead","value")); // Check with periodic HK {string,int,double,double,double,double} hkparms = PeriodicHKParms("normal"); int hkpackets = iceil(hkparms{2} + hkparms{4}); pmax = pmax - hkpackets; // Dead packets int deadstartpackets = iceil(dlookup("datarates","dead_startpackets","value")); int deadifpackets = iceil(dlookup("datarates","dead_ifpackets","value")); int deadwbsstartsize = iceil(dlookup("datarates","dead_wbsstartsize","value")); int deadwbsifsize = iceil(dlookup("datarates","dead_wbsifsize","value")); int deadhrsstartsize = iceil(dlookup("datarates","dead_hrsstartsize","value")); int deadhrsifsize = iceil(dlookup("datarates","dead_hrsifsize","value")); // sum up channels int n_wchannels = 0; int packets = 0; int allbits = 0; int allhkbits = 0; int newpackets = 0; // First HRS {int,int,int,int} hrssets = HrsSubbandSelection(backendreadoutparms); int n_hchannels = hrssets{2}; int n_vchannels = hrssets{3}; if(n_hchannels > 0) { newpackets = deadstartpackets + (n_hchannels + nchannelhrs - 1) / nchannelhrs; allbits = allbits + n_hchannels * hbit + newpackets * osize + deadhrsstartsize; allhkbits = allhkbits + deadhrsifsize + deadifpackets * osize; packets = packets + newpackets + deadifpackets; } if(n_vchannels > 0) { newpackets = deadstartpackets + (n_vchannels + nchannelhrs - 1) / nchannelhrs; allbits = allbits + n_vchannels * hbit + newpackets * osize + deadhrsstartsize; allhkbits = allhkbits + deadhrsifsize + deadifpackets * osize; packets = packets + newpackets + deadifpackets; } // Now the WBS channels int maxbands = 4; // First WBS if(backendreadoutparms{2}{0}) { n_wchannels = 0; newpackets = 0; for(int i2 = 1 .. maxbands) { int newchannels = backendreadoutparms{2}{1}[i2 - 1][1] - backendreadoutparms{2}{1}[i2 - 1][0]; newpackets = newpackets + (newchannels + nchannelwbs - 1) / nchannelwbs; n_wchannels = n_wchannels + newchannels; } newpackets = deadstartpackets + newpackets; allbits = allbits + n_wchannels * wbit + newpackets * osize + deadwbsstartsize; allhkbits = allhkbits + deadwbsifsize + deadifpackets * osize; packets = packets + newpackets + deadifpackets; } // Second WBS if(backendreadoutparms{3}{0}) { n_wchannels = 0; newpackets = 0; for(int i3 = 1 .. maxbands) { newchannels = backendreadoutparms{3}{1}[i3 - 1][1] - backendreadoutparms{3}{1}[i3 - 1][0]; newpackets = newpackets + (newchannels + nchannelwbs - 1) / nchannelwbs; n_wchannels = n_wchannels + newchannels; } newpackets = deadstartpackets + newpackets; allbits = allbits + n_wchannels * wbit + newpackets * osize + deadwbsstartsize; allhkbits = allhkbits + deadwbsifsize + deadifpackets * osize; packets = packets + newpackets + deadifpackets; } // Now compute minimum time; int tdatamin = (packets + pmax - 1) / pmax; if(tdatamin < 1) { CError("Internal error: Too low packet rate computed."); } // Data rates in bit/s are returned double sciencerate = double(allbits) / double(data_time); double stdhkrate = hkparms{3}; double hkrate = stdhkrate + double(allhkbits) / double(data_time); return {tdatamin,[sciencerate,stdhkrate,hkrate]}; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure SScanDBS_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int data_time = 4; // chunk size int n_bchop = 1; // Normal number of chop cycles per frequency and pointing int n_long = 1; // Chop cycles per frequency and pointing without retuning int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency double avnumchop = 1.0; // Average number of chop cycles per frequency double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute parameters for the instrument timing in normal phases {double,double} tinst = GetInstDeadSlowChop(data_time,2 * n_long,"chop",band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * 2 * n_long) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdeadint = tdeadint - double(n_long) * tinst{1}; // treat integration times of other frequencies as dead time double tdeadother = double(data_time * 4 * n_long); // Store double tswitch = tinst{1}; // Integration time double tphaseint = tinst{0}; // Correcton in case of cycles with shorter integrations if(n_cycles > 1) { tinst = GetInstDeadSlowChop(data_time,2 * n_bchop,"chop",band,lo_freq,backendreadoutparms); // dead time double tdeadshort = double(data_time * 2 * n_bchop) - tinst{0}; // subtract dead times in switches tdeadshort = tdeadshort - double(n_bchop) * tinst{1}; // weigh tdeadint = (tdeadint * double(n_cycles - 1) + tdeadshort) / double(n_cycles); tphaseint = (tphaseint * double(n_cycles - 1) + tinst{0}) / (2.0 * avnumchop * double(n_cycles)); tdeadother = (tdeadother * double(n_cycles - 1) + double(data_time * 4 * n_bchop)) / double(n_cycles); } else { tphaseint = tphaseint / (2.0 * avnumchop); } // Total dead time per cycle double tdead_tot = tdead + 2.0 * tdeadint; // Add integration times of other frequencies as dead time tdead_tot = tdead_tot + double(grouplen - 1) * tdeadother; return {tdead_tot,tphaseint,tswitch}; } //////////////////////////////////// // DBS cross observing mode - special version for Jupiter // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcJupiterDBSCross { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the two raster lines int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-Jupiter-DBS-Cross",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer // Two changes relative to the normal DBS raster // 1) The longer load duration is enforced by zero resolution {double,double} loadResolution = {0.0,effResolution{1}}; // 2) I assume that the tuning duration does not depend on the tuning level // so that the normal pre_timing can be reused. {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(2,npoints,band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,double[],double[],int[],double,double,int,int,int,int,int,int} tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = custom_map_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSCross_post_timing(pre_timing,telescopetimes,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBSCross_telescope(naifid,onPosition,stepsize,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = custom_map_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int scansize = post_timing{1}{10}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { JupiterDBSRaster_commanding(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,true); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,2,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Correct for double counting of central point // The central point is returned only double multiplier = sqrt(0.5); noisevalues{0} = noisevalues{0} * multiplier; noisevalues{1} = noisevalues{1} * multiplier; noisevalues{2} = noisevalues{2} * multiplier; noisevalues{3} = noisevalues{3} * multiplier; noisevalues{4} = noisevalues{4} / multiplier; // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {int,double,double,double,double,double} obs HifiSScanModeLoadChopNoRef { string modeName = "load-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-SScan-LoadChop-NoReference",{data_time,0,0,0,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanLoadChopNoRef_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,n_cycles,n_freq_point,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar = Fine_telescope(naifid,onPosition,band,reffreq,pre_timing{0}); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing = SScanChopNoRef_post_timing(pre_timing{0},telescopetimes); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = Fine_telescope(naifid,onPosition,band,reffreq,post_timing{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int loadlength = post_timing{1}{2}; int n_per_on = post_timing{1}{4}; int n_load_on = post_timing{1}{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanLoadChopNoRef_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_per_on,n_load_on,groupnumber,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("lchop",band,reffreq,hr1,hr2,wb1,wb2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = SScanChopNoRef_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,n_per_on * imax(n_load_on,1),false,tscan,tdead); // Evaluate performance SScanChopNoRef_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_per_on * imax(n_load_on,1),groupnumber * n_freq_point,false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure DBSRaster_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval int n_chop = 3; // number of chop cycles in one integration int n_load = 0; // number of integrations in one pointing phase int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Special meaning of n_load here if(n_load == 0) { int n_seq = 1; } else { n_seq = n_load; } // Compute parameters for the instrument timing {double,double} tinst = GetInstDeadSlowChop(data_time,2 * n_chop,"chop",band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * 2 * n_chop) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdeadint = tdeadint - double(n_chop) * tinst{1}; // Total dead time per cycle, only one point still not covered double tdead_tot = tdead + double(2 * n_seq) * tdeadint; // Integration time double tphaseint = tinst{0} / double(2 * n_chop); return {tdead_tot,tphaseint,tinst{1}}; } //HIFI LO tuning for FSW and no cases, block //Settings for both frequencies need to be common //and are passed through lo_freq_setting //Target current is read from look-up table block LO_tuning_block_aot HIFI 6616 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency at which to set LSU double lo_freq_setting = 978.3; //LO frequency at which to take the settings string mixer_polarization = "H" in ["H","V","B"]; //The polarization to be used for the tuning bool clearflags = true; // whether to reset LCU bool newsetting = true; // whether LSU/LOU parameters are new bool fswstorage = true; // whether FSW register shall be stored }{ //Store rest frequency double rest_lofreq = lo_freq; //LO frequency uncorrected from VelCorr double rest_lofreq_setting = lo_freq_setting; // Perform radial velocity correction lo_freq = VelCorrFreq(rest_lofreq); lo_freq_setting = VelCorrFreq(rest_lofreq_setting); //Get target mixer current {double,string}[] result = ConfigurationReader("name_confilmix",["target_mx_c_h","target_mx_c_v"],band,lo_freq); double target_current = result[0]{0}; if(mixer_polarization == "V") { target_current = result[1]{0}; } if(mixer_polarization == "B") { target_current = 0.5 * (result[1]{0} + result[0]{0}); } // //Fetch LO parameters string name_configlo = "name_configlo_a"; string name_configlcu = "name_configlcu_a"; string name_confindex = "name_confindex_a"; string name_configlotune = "name_configlotune_a"; string name_configlcutune = "name_configlcutune_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlo = "name_configlo_b"; name_configlcu = "name_configlcu_b"; name_confindex = "name_confindex_b"; name_configlotune = "name_configlotune_b"; name_configlcutune = "name_configlcutune_b"; } // result = ConfigurationReader(name_configlotune,["step_drain2_v","nsteps","step_time"],band,lo_freq); double step_drain2_v = result[0]{0}; int nsteps = iround(result[1]{0}); double step_time = result[2]{0}; // result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step"],band,lo_freq_setting); double plevel_v = result[0]{0}; double m1_v = result[1]{0}; double m2_v = result[2]{0}; double m3_v = result[3]{0}; int d2_step = iround(result[4]{0}); // double[] cresult = CalibrationReader("name_lcu_safe_values",["g1_v","g2_v","d1_v","d2_v"],band,lo_freq); double gate1_v = cresult[0]; double gate2_v = cresult[1]; double drain1_v = cresult[2]; double drain2_v_start = cresult[3]; // result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq); int freq_nx = ifloor(result[0]{0}); //Compute lsu_main and offset int[] resu = ComputeLSU_A_M_R(band,lo_freq); int lsu_main = resu[0]; int lsu_offset = resu[1]; //Get checksum result = ConfigurationReader("name_delays",["cus_checksum"],band,lo_freq); int macro_checksum = iround(result[0]{0}); // result = ConfigurationReader(name_configlo,["curlim1_v","curlim2_v"],band,lo_freq); string curlim1 = result[0]{1}; string curlim2 = result[1]{1}; // double step_PL_C = 0.0; double step_m1_v = 0.0; double step_m2_v = 0.0; double step_m3_v = 0.0; double step_gate1_v = 0.0; double step_gate2_v = 0.0; double step_drain1_v = 0.0; // //Adjust scan cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,rest_lofreq); double drain2_safe = cresult[0]; // double drain2_bluemax = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq); // //For all bands, scan will be done with decreasing drain2 voltages //The best guess is taken from look-up table double tune_range = 0.1; result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq); double v_d2 = result[0]{0}; drain2_v_start = min(v_d2 * (1.0 + tune_range / 2.0),drain2_bluemax); double drain2_v_end = (1.0 - tune_range / 2.0) / (1.0 + tune_range / 2.0) * drain2_v_start; step_drain2_v = (drain2_v_end - drain2_v_start) / double(nsteps - 1); // //Recovey from potential failure mode if(clearflags) { Set_LO_Nominal_proc_aot(); } // // Commanding of new parameters only if needed if(newsetting) { // Get all parameters needed to compute config_lo_delay in Configure_LCU // //Compute largest delay possible anticipating worst redshift // Maximum redshift given by maximum accepted radial velocity // Needs to be compliant with code in VelCorr // maxredshift=1 + 30.7km/s / 299999.6km/s; double maxredshift = 1.0001023; double drain2_bluemax_lowredshift = Get_BLUE_LIMIT_D2_proc_fm(band,rest_lofreq / maxredshift); result = ConfigurationReader(name_configlcutune,["drain2_v"],band,rest_lofreq / maxredshift); double drain2_lowredshift = min(result[0]{0} * (1.0 + tune_range / 2.0),drain2_bluemax_lowredshift); double drain2_bluemax_highredshift = Get_BLUE_LIMIT_D2_proc_fm(band,rest_lofreq * maxredshift); result = ConfigurationReader(name_configlcutune,["drain2_v"],band,rest_lofreq * maxredshift); double drain2_highredshift = min(result[0]{0} * (1.0 + tune_range / 2.0),drain2_bluemax_highredshift); // // Finally get config_lo_delay result = ConfigurationReader("name_delays",["lock_lo_delay","vd2_rampup_speed"],band,rest_lofreq); int config_lo_delay = iceil(result[0]{0} + (max(drain2_lowredshift,drain2_highredshift) - drain2_safe) / result[1]{0}); // //Send command HIFI_Configure_LCU_proc_aot(band,lo_freq,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,macro_checksum,config_lo_delay); // //TM page dump and error flag clearance now contained in the above proc } // //Load vector scan //Check which LO band is used if(band == "1a") { //Band 1a Hifi_HIFI_Load_vector_safe_1a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "1b") { //Band 1b Hifi_HIFI_Load_vector_safe_1b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "2a") { //Band 2a Hifi_HIFI_Load_vector_safe_2a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "2b") { //Band 2b Hifi_HIFI_Load_vector_safe_2b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "3a") { //Band 3a Hifi_HIFI_Load_vector_safe_3a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "3b") { //Band 3b Hifi_HIFI_Load_vector_safe_3b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "4a") { //Band 4a Hifi_HIFI_Load_vector_safe_4a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "4b") { //Band 4b Hifi_HIFI_Load_vector_safe_4b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v_start,curlim2,macro_checksum,step_drain2_v); } if(band == "5a") { //Band 5a Hifi_HIFI_Load_vector_nom_5a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,step_PL_C,step_m1_v,step_m2_v,step_gate1_v,step_gate2_v,step_drain1_v,step_drain2_v); } if(band == "5b") { //Band 5b Hifi_HIFI_Load_vector_nom_5b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,step_PL_C,step_m1_v,step_m2_v,step_gate1_v,step_gate2_v,step_drain1_v,step_drain2_v); } if(band == "6a") { //Band 6a Hifi_HIFI_Load_vector_nom_6a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,step_PL_C,step_m1_v,step_m2_v,step_m3_v,step_gate1_v,step_gate2_v,step_drain1_v,step_drain2_v); } if(band == "6b") { //Band 6b Hifi_HIFI_Load_vector_nom_6b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,step_PL_C,step_m1_v,step_m2_v,step_gate1_v,step_gate2_v,step_drain1_v,step_drain2_v); } if(band == "7a") { //Band 7a Hifi_HIFI_Load_vector_nom_7a($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,step_PL_C,step_m1_v,step_m2_v,step_gate1_v,step_gate2_v,step_drain1_v,step_drain2_v); } if(band == "7b") { //Band 7b Hifi_HIFI_Load_vector_nom_7b($BBID,nsteps,step_time,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v_start,curlim2,step_PL_C,step_m1_v,step_m2_v,step_gate1_v,step_gate2_v,step_drain1_v,step_drain2_v); } // //Execute tuning: check which mixer is to be used if(mixer_polarization == "V") { if(band == "5a" || band == "5b") { Hifi_HIFI_Tune_LO5_Using_MXCV($BBID,target_current); } else { Hifi_HIFI_Tune_LO_Using_MXCV($BBID,target_current); } } else { if(band == "5a" || band == "5b") { Hifi_HIFI_Tune_LO5_Using_MXCH($BBID,target_current); } else { Hifi_HIFI_Tune_LO_Using_MXCH($BBID,target_current); } } // double time_needed = double(nsteps) * step_time; delay(iround(time_needed + 2.0 + 0.5)); //0.5s added for completion of load_vector // //Store settings into available register if(fswstorage) { HIFI_HL_store_tm_proc_fm(); } // //Read TM pages and clear error flags after vector scan LCU_Read_TM_pages_proc_aot(); } //General LO configuration command block HIFI_Configure_LCU_block_aot HIFI 6617 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency int freq_nx = 0; // HL_freq_nx int lsu_main = 0; // HL_LSU_main int lsu_offset = 0; // HL_LSU_offset int d2_step = 1; // HL_D2_step double plevel_v = 0.0; double m1_v = 9.0; double m2_v = -2.0; double m3_v = 0.0; double gate1_v = -2.5; double gate2_v = -2.5; double drain1_v = 2.8; string curlim1_v = "1.4"; double drain2_v = 2.6; string curlim2_v = "1.4"; int macro_checksum = 0; // HL_macro_checksum int config_lo_delay = 6; }{ //Check that Vd2 is within the blue limits drain2_v = Check_BLUE_LIMIT_D2_proc_fm(band,lo_freq,drain2_v); // // //Execute configuration //Check which LO band is used if(band == "1a") { //Band 1a Hifi_HIFI_Conf_safe_LCU_ch1a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "1b") { //Band 1b Hifi_HIFI_Conf_safe_LCU_ch1b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "2a") { //Band 2a Hifi_HIFI_Conf_safe_LCU_ch2a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "2b") { //Band 2b Hifi_HIFI_Conf_safe_LCU_ch2b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "3a") { //Band 3a Hifi_HIFI_Conf_safe_LCU_ch3a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "3b") { //Band 3b Hifi_HIFI_Conf_safe_LCU_ch3b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "4a") { //Band 4a Hifi_HIFI_Conf_safe_LCU_ch4a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "4b") { //Band 4b Hifi_HIFI_Conf_safe_LCU_ch4b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "5a") { //Band 5a Hifi_HIFI_Conf_nom_LCU_ch5a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "5b") { //Band 5b Hifi_HIFI_Conf_nom_LCU_ch5b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "6a") { //Band 6a Hifi_HIFI_Conf_nom_LCU_ch6a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "6b") { //Band 6b Hifi_HIFI_Conf_nom_LCU_ch6b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "7a") { //Band 7a Hifi_HIFI_Conf_nom_LCU_ch7a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "7b") { //Band 7b Hifi_HIFI_Conf_nom_LCU_ch7b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } // delay(config_lo_delay); // //Read TM pages and clear error flags LCU_Read_TM_pages_proc_aot(); } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure JupiterFastDBS_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_seq = 1; // Number of continuous data transfer cycles int n_load = 0; // additional load measurements in one pointing phase int n_loadinterval = 10; // number of nods before a load measurement bool end_load = false; // Need for load after each pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration int shiftlength = 10; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int load_datatime = GetStdLoadReadout(band,lo_freq); // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time / 2); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; int[] choppars = [2 * n_int,0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"jupiter"); } delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i1 = 1 .. n_load) { HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Second phase in first nod position // occurs for even cycle numbers runintostate = false; if(state[2] % 2 == 0) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 7) { // second nod position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles for(int i2 = 1 .. n_load) { HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // First phase in second nod position // occurs for odd cycle numbers runintostate = false; if(state[2] % 2 == 1) { if(end_load) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // A nod slew follows - active HK if not used by load measurement if(state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } } if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement // ( Does not occur if end_load is set) LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } //Get maximum value for vector_scan_BLUE_LIMIT double procedure Get_BLUE_LIMIT_D2_proc_fm { string band = "4a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO Frequency }{ //Remove this when SCR2220 implemented string name_confindex = "name_confindex_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_confindex = "name_confindex_b"; } {double,string}[] result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq); int freq_nx = ifloor(result[0]{0}); //Fetch D2 blue min and max result = ConfigurationReader("name_configlcublue",["blmn1a","blmx1a","blmn1b","blmx1b","blmn2a","blmx2a","blmn2b","blmx2b","blmn3a","blmx3a","blmn3b","blmx3b","blmn4a","blmx4a","blmn4b","blmx4b","blmn5a","blmx5a","blmn5b","blmx5b","blmn6a","blmx6a","blmn6b","blmx6b","blmn7a","blmx7a","blmn7b","blmx7b"],band,double(freq_nx)); //Anticipated implementation of SCR-2220: not yet active until we get the first set of files string name_configlcu = "name_configlcu_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlcu = "name_configlcu_b"; } //{double, string}[] result = ConfigurationReader(name_configlcu, // ["drain2_v_blmn","drain2_v_blmx"],band, lo_freq); //Fetch offset to apply to blue max double[] cresult = CalibrationReader("name_blueoffset",["blueoffset"],band,0.0); double bloff = cresult[0]; // double drain2_max = 0.0; if(band == "1a") { drain2_max = result[1]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "1b") { drain2_max = result[3]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "2a") { drain2_max = result[5]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "2b") { drain2_max = result[7]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "3a") { drain2_max = result[9]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "3b") { drain2_max = result[11]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "4a") { drain2_max = result[13]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "4b") { drain2_max = result[15]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "5a") { drain2_max = result[17]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "5b") { drain2_max = result[19]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "6a") { drain2_max = result[21]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "6b") { drain2_max = result[23]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "7a") { drain2_max = result[25]{0} - bloff; //drain2_max = result[1]{0}-bloff; } if(band == "7b") { drain2_max = result[27]{0} - bloff; //drain2_max = result[1]{0}-bloff; } return drain2_max; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF observing mode {int,int,int,int,bool,int,int} procedure OTFFSwitchNoRef_pre_timing { int nlines = 1; // Number of rows in the map int npoints = 10; // Number of data dumps per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_chop_on = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles per point int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq + min(freq_throw,0.0),lo_freq + max(freq_throw,0.0)); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); CheckFswOutOfBand(band,lo_freq,freq_throw,backendreadoutparms); // jitter treatment is already taken into account by ValidMapSize // Compute parameters for the instrument timing int lineint = npoints * n_chop_on * 2 * data_time; int nlines_tot = nlines * n_cycles; // compute load integration time int loadlength = duration(DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compute the scan size from the load interval int load_spacing = CheckedLoadSpacing(load_interval - loadlength,npoints * 8); // Here, we do not know the turn around-time yet. Ignored until post_timing int n_loadinterval = load_spacing / lineint; if(n_loadinterval < 1) { SError("Scan duration too long for load period. " + "Reduce the number of chop cycles."); } // Make sure that load slews occur at the same position in each coverage CheckReasonableLineNumber(nlines,true); n_loadinterval = IMultiple(n_loadinterval,nlines); // If no load required parameter has to be 0 if(n_loadinterval > nlines_tot) { // Determine need for final load measurement double rest = double(nlines_tot % n_loadinterval) + 0.5; bool end_load_on = rest > 0.5001 * double(n_loadinterval); } else { if(n_loadinterval > nlines) { n_loadinterval = nlines; } // In all these cases a final load will be made anyway in regular pattern end_load_on = false; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,true); } initlength = initlength + loadlength; // Dangling load measurement not counted here, only dangling readout int dangling = readoutdead; // Return all the times needed in the observing mode modules // The holdlength parameter is abused for lineint here return {loadlength,load_spacing,n_loadinterval,lineint,end_load_on,initlength,dangling}; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure OTF_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int nlines = 20; // Number of lines in the map int npoints = 20; // Number of points in the map int n_scans = 2; // Number of OTF scans to cover the map int n_cycles = 1; // Number of map coverages double tscan = 60.0; // Total average duration of one scan {double,double,double} tact = {10.0,4.0,12.0}; // field of actual timings }{ double tint_act = tact{1}; // integration time excluding all dead times double tintoff = tact{2}; // integration time on OFF // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; // rescale for map coverage idealnoise = idealnoise * double(npoints * nlines); double efficiency = idealnoise / obsnoise; // Compute the actual integration time double posinttime = double(n_cycles * nlines * npoints) * tint_act; double posofftime = double(n_cycles * n_scans + 1) * tintoff; int instrumenttime = iceil(double(n_cycles * n_scans) * tscan + tintoff); // Check total integration time double timeefficiency = (posinttime + posofftime) / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // Non-standard messages message("

"); message("The observed map consists of " + nlines + " OTF lines, each covering " + npoints + " readout points.
"); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posofftime,timeefficiency,efficiency,relnoise,false); } // Procedure for zero and comb measurement // Collects all common parts for LoadMeasurement and DoubleLoadMeasurement // procedure ZeroCombMeasurement { string band = "4a"; // HIFI band (needed to estimate stabilization) double lo_freq = 978200.0; // LO frequency int used_datatime = 4; // time between subsequent data readouts in load {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 }{ // Usage of WBS bool wbs1used = backendreadoutparms{2}{0}; bool wbs2used = backendreadoutparms{3}{0}; // Zero and Comb measurement is only used in WBS observations if(wbs1used || wbs2used) { // Now start the zero-comb measurement int danglingreadout = WBS_Zero_Comb(band,lo_freq); // Add possible delay needed before next zero measurement if(used_datatime < danglingreadout) { delay(danglingreadout - used_datatime); } // Perform the first zero measurement with the settings of the // regular observations // // I use the optimistic approach to completely omit this step now // danglingreadout=WBS_Full_Zero(band,lo_freq,used_datatime, // backendreadoutparms); // // Add possible delay needed before hot-cold measurement // if (used_datatime < danglingreadout) { // delay(danglingreadout-used_datatime); // } } } // Total power integration for peak up block HIFIPeakupIntegration HIFI 6821 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // number of readouts bool isWbs = true; // backend to use - resolution bool isH = true; // backend to use - polarization int point = 1; // Number of point in 3x3 raster string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ // First part - actual peakup data aquisition // polarization string if(isH) { string polarization = "H"; } else { polarization = "V"; } // Call command if(isWbs) { Hifi_HIFI_acquire_peakup_wbs($BBID,polarization,point); } else { Hifi_HIFI_acquire_peakup_hrs($BBID,polarization,point); } delay(2); // Second part additional data frame aquisition HIFI_Spectr_slow_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3","chop_M3right"],rates); // Move chopper back to center position RotateChopper(band,lo_freq,"chop_M3"); } //////////////////////////////////// // Frequency switch observing mode // // All properties inherited from the load-chop mode // // This whole implementation is highly speculative as we have no experience // with frequency switch measurements yet. // {int,double,double,double,double,double} obs HifiPointProcFSwitch { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_switch_off = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-FSwitch",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,0,n_cycles,load_interval}); // position switch // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing_ps = FSwitch_pre_timing(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,pre_timing_ps,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},int,bool,double,double} post_timing_ps = DoubleChop_post_timing(pre_timing_ps,telescopetimes,n_cycles); // Now the actual observation starts // Prepare telescope command tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,post_timing_ps{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Consistency check int totaltime = post_timing_ps{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// int on_inttime = post_timing_ps{1}{0}; int off_inttime = post_timing_ps{1}{1}; int on_pointing = post_timing_ps{1}{2}; int off_pointing = post_timing_ps{1}{3}; int loadlength = post_timing_ps{1}{4}; int n_loadinterval = post_timing_ps{1}{7}; int n_per_on = post_timing_ps{1}{8}; int n_per_off = post_timing_ps{1}{9}; int n_load_on = post_timing_ps{1}{10}; int n_load_off = post_timing_ps{1}{11}; bool end_load_on = post_timing_ps{1}{12}; bool end_load_off = post_timing_ps{1}{13}; int initshiftlength = post_timing_ps{2}; bool final_load = post_timing_ps{3}; double tscan = post_timing_ps{4}; double tdead = post_timing_ps{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FSwitch_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_loadinterval,n_load_on,n_load_off,end_load_on,end_load_off,final_load,startobs,telescopetimes,loadlength,initshiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = DoubleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_load_on,n_load_off,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = FSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance DoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_per_on * (n_load_on + 1),n_per_off * (n_load_off + 1),true,tscan,on_pointing,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Compute the offset between two points // This is an approximation for small offsets {double,double} procedure AngularOffset { {double,double} vector1 = {0.0,0.0}; // First vector {double,double} vector2 = {0.2,0.2}; // Second vector }{ double pih = 3.14159265 / 2.0; double pideg = pih / 90.0; double l1 = vector1{0} * pideg; double b1 = vector1{1} * pideg; double l2 = vector2{0} * pideg; double b2 = vector2{1} * pideg; // 3-D vector double u1 = cos(b2) * cos(l2); double u2 = cos(b2) * sin(l2); double u3 = sin(b2); // Rotate by l1 double s1 = cos(l1) * u1 + sin(l1) * u2; double s2 = -sin(l1) * u1 + cos(l1) * u2; double s3 = u3; // Rotate by b1 u1 = cos(b1) * s1 + sin(b1) * s3; u2 = s2; u3 = -sin(b1) * s1 + cos(b1) * s3; // Extract angles double u12 = sqrt(u1 * u1 + u2 * u2); if(u12 > 0.0) { double db = atan(u3 / u12); } else { db = pih; } if(u1 != 0.0) { double dl = atan(u2 / u1); } else { dl = pih; } return {dl / pideg,db / pideg}; } // Total noise from a symmetric two-phase observation // This is still to be scaled by a factor 1.0/(B_fluct*T_obs) double procedure TwoPhaseNoise { double x = 0.1; // value for integration time relative to Allan time double[] parameters = [0.3,2.5]; // Parameters: delay relative to Allan time, drift exponent }{ // Assign parameters double d = parameters[0]; double alpha = parameters[1]; // add radiometric and drift noise double yn = TwoPhaseRadioNoise(x); double yd = TwoPhaseDrift(x,d,alpha); // Add and normalize with respect to total observing time double y = (yn + yd) * (2.0 * x + d); return y; } {string,double,double}[] procedure HifiMappingModeFastDBSRasterSequencerInit { string modeName = "raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities // Top down approach here int main_phase = iceil(phaselengths{0}); // Arbitrary selection of data_time int data_time_guess = 20; // Combine points for n_switch=1 int n_pointsperscan_guess = imin(imax(main_phase / data_time_guess,1),npoints * nlines); int n_pointsperscan_range = 1 - n_pointsperscan_guess; if(n_pointsperscan_range == 0) { n_pointsperscan_range = 1; } // remaining part for n_switch int n_switch_on_guess = main_phase / (n_pointsperscan_guess * data_time_guess) + 1; data_time_guess = main_phase / (n_pointsperscan_guess * n_switch_on_guess); // Check with data rate {int,double[]} dataparms = DataTaking(backendreadoutparms,8); int datalimit = 2 * dataparms{0}; if(data_time_guess < datalimit) { data_time_guess = datalimit; n_switch_on_guess = 1; } int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Chop phase length double phase_min = min(max(phaselengths{1},0.15),1.5); int n_int_on_guess = ifloor(double(data_time_guess) / (2.0 * phase_min)); int n_int_on_range = -n_int_on_guess / 2; if(n_int_on_range == 0) { n_int_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_pointsperscan",double(n_pointsperscan_guess),double(n_pointsperscan_range)}]; return retvalues; } /////////////////////////////////////////////////////// // Generic procedures to configure various S/S in HIFI //Configure FPU at frequency of interest: // - set nominal bias, magnet currents and diplexer currents // - set IF amp. to nominal // - look at internal HBB // - set chopper parameter, use of CLOSED loop // - checks whether one of the polarization is not used // - DT 250707: added code to allow LO band switch on // //Configure FPU procedure ConfigureFPU { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz bool power_fcu = true; //whether needs full FPU configuration (true) or just freq-dependent adjustement (false) }{ //We always setup both polarizations although one of them may not be used //This has only effect on data readouts, not on hardware settings Init_MSA_aot(band,"CLOSE",lo_freq / 1000.0,power_fcu,"ON"); } {int,double,double,double,double,double} obs HifiMappingModeLoadChopOTF { string modeName = "load-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-LoadChop-OTF",{data_time,data_time_off,0,n_switch_on,n_switch_off,n_linesperscan,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,int,int,int,int} pre_timing = OTFLoadChop_pre_timing(nlines,npoints_used,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_with_off_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int},double,double} post_timing = OTFmap_post_timing(pre_timing,telescopetimes,data_time,n_linesperscan,n_cycles,load_interval); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_with_off_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int n_pp = post_timing{1}{0}; int n_scans = post_timing{1}{1}; int off_inttime = post_timing{1}{2}; int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{5}; double tscan = post_timing{2}; double tdead = post_timing{3}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFLoadChop_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,npoints_used * n_switch_on,n_switch_off,nlines * n_cycles,n_linesperscan,n_loadinterval,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double,double,double} tact = OTFDoubleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,n_pp,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = OTFLoadChop_noisecomputer(band,lo_freq,effResolution,oneGHzReference,nlines,data_time,n_switch_on,n_linesperscan,off_inttime,n_cycles,tscan,tact); // Evaluate performance OTFDoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on,n_switch_off,n_scans,n_cycles,false,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // LCU configuration with no retune, block // Uses best guess D2 voltage from latest LO tuning block LCU_config_nominal_noretune_block_aot HIFI 6614 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency bool fswstorage = true; // whether FSW register shall be stored }{ //Store rest frequency double rest_lofreq = lo_freq; //LO frequency uncorrected from VelCorr // Perform radial velocity correction lo_freq = VelCorrFreq(rest_lofreq); //Fetch LO parameters string name_configlcu = "name_configlcu_a"; string name_confindex = "name_confindex_a"; if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") { name_configlcu = "name_configlcu_b"; name_confindex = "name_confindex_b"; } // {double,string}[] result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq); int freq_nx = ifloor(result[0]{0}); // //Compute lsu_main and offset int[] resu = ComputeLSU_A_M_R(band,lo_freq); int lsu_main = resu[0]; int lsu_offset = resu[1]; // result = ConfigurationReader("name_delays",["config_lo_delay"],band,rest_lofreq); int config_lo_delay = iround(result[0]{0}); //Send command Hifi_HIFI_Conf_f_LCU_noretune($BBID,freq_nx,lsu_main,lsu_offset); // delay(config_lo_delay); //Store settings into available register if(fswstorage) { HIFI_HL_store_tm_proc_fm(); } } ///////////////////////////////////////////////////////////////// // Slow chop dual beam switch observing mode // // Combination of four modules implementing the new structure // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiPointProcDBS { /* Setup parameters */ int naifid = 0; // Tracing object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-DBS",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = DBS_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} post_timing = DBS_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_seq = post_timing{1}{8}; int n_loadinterval = post_timing{1}{7}; bool end_load = post_timing{1}{9}; int shiftlength = post_timing{1}{10}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { DBS_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,n_loadinterval,end_load,final_load,startobs,telescopetimes,loadlength,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = DBS_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBS_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_seq * (n_load + 1),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Function allowing to derive HRS internal LO parameters A and M // in function of requested frequencies. // - The first 4 IF are given in GHz between 4 and 8 GHz // - The 5th and 6th LOs (fixed) are given in GHz // - The 7th LO is given in MHz // // The rules are: // - 64 <= M <= 84, 0 <= A <= 9 // - Flo = 200x(M+1)+20xA // with Flo in 13-17.180 GHz, i.e. 9GHz above IF // // The result array is organized as follows: // [A1_h,M1_H, A2_H,...A7_h,A1_v,M1_v,A2_v,..,A7_v] // // DT - 3 June 2005 int[] procedure ComputeA_M_parameters { string[] hrs_mode = ["wb","wb"]; //HRS resolution mode for both polar: hr, mr, lr, wb double hrh_up_ol1 = 4.5; // IF1 frequency for H-polar double hrh_up_ol2 = 4.5; // IF2 frequency for H-polar double hrh_up_ol3 = 4.5; // IF3 frequency for H-polar double hrh_up_ol4 = 4.5; // IF4 frequency for H-polar double hrh_down_ol5 = 10.5; // LO5 frequency for H-polar double hrh_down_ol6 = 1.25; // LO6 frequency for H-polar double hrh_down_ol7 = 490.0; // LO7 frequency for H-polar double hrv_up_ol1 = 4.5; // IF1 frequency for V-polar double hrv_up_ol2 = 4.5; // IF2 frequency for V-polar double hrv_up_ol3 = 4.5; // IF3 frequency for V-polar double hrv_up_ol4 = 4.5; // IF4 frequency for V-polar double hrv_down_ol5 = 10.5; // LO5 frequency for V-polar double hrv_down_ol6 = 1.25; // LO6 frequency for V-polar double hrv_down_ol7 = 490.0; // LO7 frequency for V-polar }{ //Initialize array //Defaults are: lo1=13, lo2=14, lo3=15, lo4=16 GHz int[] a_m_parameter = [0,64,0,64,0,64,0,64,5,51,0,49,7,0,64,0,64,0,64,0,64,5,51,0,49,7]; int[] a_m = [0,0]; // //The number of A and M parameters to compute depends on the mode // //First rename LO7 and convert to GHz double flo7_h = hrh_down_ol7 / 1000.0; double flo7_v = hrv_down_ol7 / 1000.0; //Initialize freq. double flo_u1_h = 0.0; double flo_u1_v = 0.0; double flo_l2_h = 0.0; double flo_l2_v = 0.0; double flo_u3_h = 0.0; double flo_u3_v = 0.0; double flo_l4_h = 0.0; double flo_l4_v = 0.0; // //High-Resolution if(hrs_mode[0] == "hr") { //H-polar flo_u1_h = (9.25 - flo7_h / 4.0 + hrh_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_h = Check_HRS_prohibited_LO_proc_fm(flo_u1_h); a_m = GetA_M(flo_u1_h); a_m_parameter[0] = a_m[0]; a_m_parameter[1] = a_m[1]; } // if(hrs_mode[1] == "hr") { //V-polar flo_u1_v = (9.25 - flo7_v / 4.0 + hrv_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_v = Check_HRS_prohibited_LO_proc_fm(flo_u1_v); a_m = GetA_M(flo_u1_v); a_m_parameter[13] = a_m[0]; a_m_parameter[14] = a_m[1]; } // //Medium-Resolution if(hrs_mode[0] == "mr") { //H-polar flo_u1_h = (9.25 - flo7_h / 4.0 + hrh_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_h = Check_HRS_prohibited_LO_proc_fm(flo_u1_h); a_m = GetA_M(flo_u1_h); a_m = GetA_M(flo_u1_h); a_m_parameter[0] = a_m[0]; a_m_parameter[1] = a_m[1]; flo_l4_h = (9.25 + flo7_h / 4.0 + hrh_up_ol4) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l4_h = Check_HRS_prohibited_LO_proc_fm(flo_l4_h); a_m = GetA_M(flo_l4_h); a_m_parameter[6] = a_m[0]; a_m_parameter[7] = a_m[1]; } // //Medium-Resolution if(hrs_mode[1] == "mr") { //V-polar //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_v = Check_HRS_prohibited_LO_proc_fm(flo_u1_v); flo_u1_v = (9.25 - flo7_v / 4.0 + hrv_up_ol1) * 1000.0; a_m = GetA_M(flo_u1_v); a_m_parameter[13] = a_m[0]; a_m_parameter[14] = a_m[1]; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l4_v = Check_HRS_prohibited_LO_proc_fm(flo_l4_v); flo_l4_v = (9.25 + flo7_v / 4.0 + hrv_up_ol4) * 1000.0; a_m = GetA_M(flo_l4_v); a_m_parameter[19] = a_m[0]; a_m_parameter[20] = a_m[1]; } // //Low-Resolution if(hrs_mode[0] == "lr") { //H-polar flo_u1_h = (9.25 - flo7_h / 4.0 + hrh_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_h = Check_HRS_prohibited_LO_proc_fm(flo_u1_h); a_m = GetA_M(flo_u1_h); a_m_parameter[0] = a_m[0]; a_m_parameter[1] = a_m[1]; flo_l2_h = (9.25 + flo7_h / 4.0 + hrh_up_ol2) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l2_h = Check_HRS_prohibited_LO_proc_fm(flo_l2_h); a_m = GetA_M(flo_l2_h); a_m_parameter[2] = a_m[0]; a_m_parameter[3] = a_m[1]; flo_u3_h = (9.25 - flo7_h / 4.0 + hrh_up_ol3) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u3_h = Check_HRS_prohibited_LO_proc_fm(flo_u3_h); a_m = GetA_M(flo_u3_h); a_m_parameter[4] = a_m[0]; a_m_parameter[5] = a_m[1]; flo_l4_h = (9.25 + flo7_h / 4.0 + hrh_up_ol4) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l4_h = Check_HRS_prohibited_LO_proc_fm(flo_l4_h); a_m = GetA_M(flo_l4_h); a_m_parameter[6] = a_m[0]; a_m_parameter[7] = a_m[1]; } // //Low-Resolution if(hrs_mode[1] == "lr") { //V-polar flo_u1_v = (9.25 - flo7_v / 4.0 + hrv_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_v = Check_HRS_prohibited_LO_proc_fm(flo_u1_v); a_m = GetA_M(flo_u1_v); a_m_parameter[13] = a_m[0]; a_m_parameter[14] = a_m[1]; flo_l2_v = (9.25 + flo7_v / 4.0 + hrv_up_ol2) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l2_v = Check_HRS_prohibited_LO_proc_fm(flo_l2_v); a_m = GetA_M(flo_l2_v); a_m_parameter[15] = a_m[0]; a_m_parameter[16] = a_m[1]; flo_u3_v = (9.25 - flo7_v / 4.0 + hrv_up_ol3) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u3_v = Check_HRS_prohibited_LO_proc_fm(flo_u3_v); a_m = GetA_M(flo_u3_v); a_m_parameter[17] = a_m[0]; a_m_parameter[18] = a_m[1]; flo_l4_v = (9.25 + flo7_v / 4.0 + hrv_up_ol4) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l4_v = Check_HRS_prohibited_LO_proc_fm(flo_l4_v); a_m = GetA_M(flo_l4_v); a_m_parameter[19] = a_m[0]; a_m_parameter[20] = a_m[1]; } // //Wide-Band if(hrs_mode[0] == "wb") { //H-polar flo_u1_h = (9.25 + hrh_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_h = Check_HRS_prohibited_LO_proc_fm(flo_u1_h); a_m = GetA_M(flo_u1_h); a_m_parameter[0] = a_m[0]; a_m_parameter[1] = a_m[1]; flo_l2_h = (9.25 + hrh_up_ol2) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l2_h = Check_HRS_prohibited_LO_proc_fm(flo_l2_h); a_m = GetA_M(flo_l2_h); a_m_parameter[2] = a_m[0]; a_m_parameter[3] = a_m[1]; flo_u3_h = (9.25 + hrh_up_ol3) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u3_h = Check_HRS_prohibited_LO_proc_fm(flo_u3_h); a_m = GetA_M(flo_u3_h); a_m_parameter[4] = a_m[0]; a_m_parameter[5] = a_m[1]; flo_l4_h = (9.25 + hrh_up_ol4) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l4_h = Check_HRS_prohibited_LO_proc_fm(flo_l4_h); a_m = GetA_M(flo_l4_h); a_m_parameter[6] = a_m[0]; a_m_parameter[7] = a_m[1]; } // //Wide-Band if(hrs_mode[1] == "wb") { //V-polar flo_u1_v = (9.25 + hrv_up_ol1) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u1_v = Check_HRS_prohibited_LO_proc_fm(flo_u1_v); a_m = GetA_M(flo_u1_v); a_m_parameter[13] = a_m[0]; a_m_parameter[14] = a_m[1]; flo_l2_v = (9.25 + hrv_up_ol2) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l2_v = Check_HRS_prohibited_LO_proc_fm(flo_l2_v); a_m = GetA_M(flo_l2_v); a_m_parameter[15] = a_m[0]; a_m_parameter[16] = a_m[1]; flo_u3_v = (9.25 + hrv_up_ol3) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_u3_v = Check_HRS_prohibited_LO_proc_fm(flo_u3_v); a_m = GetA_M(flo_u3_v); a_m_parameter[17] = a_m[0]; a_m_parameter[18] = a_m[1]; flo_l4_v = (9.25 + hrv_up_ol4) * 1000.0; //Implement SCR-1243: 14.4 and 14.42 GHz not allowed flo_l4_v = Check_HRS_prohibited_LO_proc_fm(flo_l4_v); a_m = GetA_M(flo_l4_v); a_m_parameter[19] = a_m[0]; a_m_parameter[20] = a_m[1]; } // //Get LO5 to LO7 // a_m = GetA_M(hrh_down_ol5 * 1000.0); a_m_parameter[8] = a_m[0]; a_m_parameter[9] = a_m[1]; a_m = GetA_M(hrv_down_ol5 * 1000.0); a_m_parameter[21] = a_m[0]; a_m_parameter[22] = a_m[1]; // //flo6 is 1.25, we use a trick here since the formula for lo6 is 25(M+1)+2.5A double flo6_h = hrh_down_ol6 + 8.75; double flo6_v = hrv_down_ol6 + 8.75; a_m = GetA_M(flo6_h * 1000.0); //should be 49,0 a_m_parameter[10] = a_m[0]; a_m_parameter[11] = a_m[1]; a_m = GetA_M(flo6_v * 1000.0); //should be 49,0 a_m_parameter[23] = a_m[0]; a_m_parameter[24] = a_m[1]; // a_m_parameter[12] = iround((flo7_h * 1000.0 - 350.0) / 20.0); //flo7 = 2(10(M+1)+A), A=5, M = M+16 a_m_parameter[25] = iround((flo7_v * 1000.0 - 350.0) / 20.0); //So 490 MHz is M=7. // //debug_print("Tuning result " + a_m_parameter); return a_m_parameter; } // Detector heater control: AOT version does not switch magnet back to normal at end block Heater_block_aot HIFI 6940 { string band = "4a"; }{ //Get name of FPU configuration file {double,string}[] result_d = ConfigurationReader("name_confilfpu",["normal_heater_time_h","normal_heater_time_v","heater_delay_h","heater_delay_v","magnet_current_max_h","magnet_current_max_v"],band,0.0); double normal_heater_time_h = result_d[0]{0}; double normal_heater_time_v = result_d[1]{0}; int heater_delay_h = iround(result_d[2]{0}); int heater_delay_v = iround(result_d[3]{0}); //Magnets need to be switched to 0 prior to the deflux Hifi_HIFI_CH1_MX_MG_C($BBID,0.0); Hifi_HIFI_CV1_MX_MG_C($BBID,0.0); delay(1); // Hifi_HIFI_HF_CH1_DHTR_C($BBID,normal_heater_time_h); delay(iceil(normal_heater_time_h / 1000.0) + 1); // int startobs = time(); //Extra delay for cooling down temperature: will be included in the V-mixer delay //delay(heater_delay_h); Hifi_HIFI_HF_CV1_DHTR_C($BBID,normal_heater_time_v); delay(iceil(normal_heater_time_v / 1000.0) + 1); //Extra delay for cooling down temperature: both mixers cool down together delay(heater_delay_v); // } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the parameters for the telescope command // and to check all input parameters {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} procedure DBS_telescope { int naifid = 0; // Tracing object ID {double,double} onposition = {0.0,0.0}; // Coordinates of the source string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string throw = ""; // Identifier for chop throw, empty is standard {int,int,int,int,int,int,int,int,int,bool,int,int,int} timing = {4,10,4,21,11,1800,0,10,1,false,0,50,0}; // full timing parameter list int n_cycles = 2; // Number of half OFF-ON-ON-OFF cycles }{ // Assign values int pointing = timing{1}; // Pointing during in one phase int loadlength = timing{3}; // Load duration int n_loadinterval = timing{7}; //No. of nods between load measurements int initlength = timing{11}; // Initial setup time int dangling = timing{12}; // Final load measurement // Create variables for telescope command string ib = GetBoresight(band,lo_freq,true); // A change of ra-dec depending on naifid may be needed double ra = onposition{0}; double dec = onposition{1}; // pattern angle and throw of the chopper direction double[] chopper = GetSkyChopThrow(band,lo_freq,throw); double nodlength = chopper[0]; double patt = chopper[1]; nodlength = max(nodlength * 3600.0,2.0); // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(n_cycles > 1200) { IError("Too many noddings. Break up the observation into smaller pieces."); } if(pointing < 10) { SError("Pointing phase length too short. Increase the number of integrations."); } if(pointing > 50000) { SError("Pointing phase length too long. Reduce the number of integrations."); } if(nodlength > 7200.0) { IError("Nodding length too long. Choose a smaller chop throw."); } // repetition at multiple frequencies not yet implemented: int thold = 0; int nhold = 0; int n_repeat = n_cycles; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,false,patt,0.0,0.0,n_repeat,nodlength,pointing,pointing,loadlength,n_loadinterval,thold,nhold}; } /////////////////////////////////////////////// // Functions useful for almost all observing modes // Perform consistency check for long observations // where readout time <= data time procedure CheckDataTaking { {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // Readout parameters for HRS1,HRS2, WBS1,WBS2 int data_time = 4; // Integration time between two data readouts }{ // Compute chunk size given by the data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); if(dataparms{0} > data_time) { SError("Maximum data rate does not allow to dump backends every " + data_time + "s."); } } // WBS configuration, block // Both polarizations are treated block WBS_config_block_aot HIFI 6625 { string band = "4a"; // HIFI band }{ //H-Polarization // {double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s","hwh_att_band4","hwh_att_band3","hwh_att_band2","hwh_att_band1","hwh_att_in"],band,0.0); string hwh_laser1_s = result_d[0]{1}; string hwh_laser2_s = result_d[1]{1}; int hwh_heater = iround(result_d[2]{0}); string hwh_latchup_s = result_d[3]{1}; int hwh_att_band4 = iround(result_d[4]{0}); int hwh_att_band3 = iround(result_d[5]{0}); int hwh_att_band2 = iround(result_d[6]{0}); int hwh_att_band1 = iround(result_d[7]{0}); int hwh_att_in = iround(result_d[8]{0}); // result_d = ConfigurationReader("name_delays",["wbs_config_delay"],band,0.0); int wbs_config_delay = iround(result_d[0]{0}); // //Configure WBS-H Hifi_HIFI_Configure_WBS_H($BBID,hwh_laser1_s,hwh_laser2_s,hwh_heater,hwh_latchup_s,hwh_att_band4,hwh_att_band3,hwh_att_band2,hwh_att_band1,hwh_att_in); // //delay(wbs_config_delay); //Wait for configuration to be applied // //V-Polarization // result_d = ConfigurationReader("name_configwbs",["hwv_laser1_s","hwv_laser2_s","hwv_heater","hwv_latchup_s","hwv_att_band4","hwv_att_band3","hwv_att_band2","hwv_att_band1","hwv_att_in"],band,0.0); string hwv_laser1_s = result_d[0]{1}; string hwv_laser2_s = result_d[1]{1}; int hwv_heater = iround(result_d[2]{0}); string hwv_latchup_s = result_d[3]{1}; int hwv_att_band4 = iround(result_d[4]{0}); int hwv_att_band3 = iround(result_d[5]{0}); int hwv_att_band2 = iround(result_d[6]{0}); int hwv_att_band1 = iround(result_d[7]{0}); int hwv_att_in = iround(result_d[8]{0}); // //Configure WBS-V Hifi_HIFI_Configure_WBS_V($BBID,hwv_laser1_s,hwv_laser2_s,hwv_heater,hwv_latchup_s,hwv_att_band4,hwv_att_band3,hwv_att_band2,hwv_att_band1,hwv_att_in); // delay(wbs_config_delay); //Wait for configuration to be applied // } //Retune HIFI - keep magnet and backends procedure HIFITuneFreqNoretune { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; //LO frequency }{ // frequency setup, stored in FSW1 register LCU_config_nominal_noretune_block_aot(band,lo_freq / 1000.0,false); // } // Check constancy of magnet current across scan procedure CheckSpectralScanRange { string band = "4a"; // HIFI band double lo_freq = 978200.0; // reference LO frequency in MHz double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz }{ // The current implementation assumes that the magnet current does not // change within a spectral scan - to be sure I add a check if(band != "6a" && band != "6b" && band != "7a" && band != "7b") { // first frequency {double,string}[] result_d = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v"],band,lo_freq / 1000.0); bool ok = true; double mxmg_h = result_d[0]{0}; double mxmg_v = result_d[1]{0}; // second frequency result_d = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v"],band,lo_freq_low / 1000.0); if(mxmg_h != result_d[0]{0} || mxmg_v != result_d[1]{0}) { ok = false; } // third frequency result_d = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v"],band,lo_freq_up / 1000.0); if(mxmg_h != result_d[0]{0} || mxmg_v != result_d[1]{0}) { ok = false; } if(!ok) { CError("Magnet field not constant across selected spectral scan range"); } } } {int,double,double,double,double,double} obs HifiPointModeLoadChopNoRef { string modeName = "load"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-LoadChop-NoReference",{data_time,0,0,0,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,bool,int,int} pre_timing_f = LoadChopNoRef_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,pre_timing_f); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing_f = SingleChopNoRef_post_timing(pre_timing_f,telescopetimes); // Now the actual observation starts // Prepare telescope command tpar_f = Fine_telescope(naifid,onPosition,band,lo_freq,post_timing_f{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar_f{0},tpar_f{1},tpar_f{2},tpar_f{3},tpar_f{4},tpar_f{5},tpar_f{6},tpar_f{7},tpar_f{8},tpar_f{9}); // Consistency check int totaltime = post_timing_f{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// // standard parameters for fine pointing int loadlength = post_timing_f{1}{2}; int n_per_on = post_timing_f{1}{4}; int n_load_on = post_timing_f{1}{5}; bool end_load_on = post_timing_f{1}{6}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { LoadChopNoRef_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on,n_load_on,end_load_on,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // There are no telescope dead times involved in this mode {double,double,double} tact = SingleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_per_on * (n_load_on + 1),tscan,tdead); // Evaluate performance SingleChopNoRef_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_per_on * (n_load_on + 1),false,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Return standard readout setting used in frequency calibration {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} procedure FrequencyCalibrationParms { bool usewbs1 = true; // whether the WBS1 is used bool usewbs2 = true; // whether the WBS2 is used bool usehrs1 = false; // whether the HRS1 is used bool usehrs2 = false; // whether the HRS2 is used }{ {bool,int,bool[]} hrs1 = {usehrs1,3,[true,true,true,true]}; {bool,int,bool[]} hrs2 = {usehrs2,3,[true,true,true,true]}; {bool,int[][]} wbs1 = {usewbs1,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {usewbs2,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {hrs1,hrs2,wbs1,wbs2}; return backendreadoutparms; } ////////////////////////////////////////////////////////////////////////// // Procedure for telescope commanding is inherited from DBS mode //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure SScanDBS_commanding { string band = "4a"; // HIFI band double reffreq = 978300.0; // Reference characteristic LO frequency {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int grouplen = 1; // Number of frequency steps per nodding phase int[][] grouporder = [[0],[0]]; // Sequence to trace frequency points in both phases double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points bool retuning = false; // need for WBS retuning double[] targetlevels = [1.0,1.0,1.0]; // WBS tuning levels int data_time = 4; // chunk size int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles at one frequency int allsteps = 4; // Total number of frequency pointing periods int n_bchop = 1; // Normal number of chop cycles per frequency and pointing int n_long = 1; // Chop cycles per frequency and pointing without retuning int n_loadinterval = 1; // number of nods before a load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int shiftlength = 10; // Shift of the loop start relative to the pointing }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points // First frequency double runningfreq = freqgrid[grouporder[0][0]]; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); // recompute load duration for initial load measurement int loadlength = duration(SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; bool retuneload = n_loadinterval > 1; // Tuning levels string[] targetnames = TargetNames(band,reffreq,retuning,targetlevels); string target = targetnames[0]; // All commands with a duration possibly depending on the frequency // are taken at the reference frequency to guarantee synchonization // Declare auxiliary variables to be used in the loops int i_freqcycles = 0; int i_group = 0; int i_phase = 0; // variables storing the configuration setting bool islong = false; bool isinvalid = true; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // HIFIInitObs(); TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},target); delay(tinitslew - (time() - startobs) - loadlength + shiftlength - hkduration); // First load measurement HIFISetHK("normal",false); SScanLoadMeasurement(band,runningfreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms); if(shiftlength > 0) { runintostate = true; } else { runintostate = false; } } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position i_phase = (state[2] + 1) % 2; // Reset group counter i_group = 0; runintostate = false; // long integrations not possible in last and first nod cycle if(n_cycles > 1 && state[2] % n_cycles != state[2] % 2) { if(isinvalid || !islong) { HIFIConfigureSlowChopIntegration(data_time,n_long,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFISlowChopOnIntegration(data_time,n_long,band,reffreq,rates); } else { if(isinvalid || islong) { HIFIConfigureSlowChopIntegration(data_time,n_bchop,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } while(i_group < grouplen - 1) { HIFISlowChopOnIntegration(data_time,n_bchop,band,reffreq,rates); // retune i_group = i_group + 1; runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen]; HIFIChangeFreq(band,runningfreq); } HIFISlowChopOnIntegration(data_time,n_bchop,band,reffreq,rates); // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && i_phase == 1) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[0][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFreq(band,runningfreq,target); runintostate = true; } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 1 && state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } if(state[0] == 7) { // second nod position i_phase = state[2] % 2; // First nodding position // Reset group counter i_group = 0; runintostate = false; // long integrations not possible in last and first nod cycle if(n_cycles > 1 && state[2] % n_cycles != (state[2] % 2 + 1) % 2) { if(isinvalid || !islong) { HIFIConfigureSlowChopIntegration(data_time,n_long,band,reffreq,backendreadoutparms); islong = true; isinvalid = false; } HIFISlowChopOffIntegration(data_time,n_long,band,reffreq,rates); } else { if(isinvalid || islong) { HIFIConfigureSlowChopIntegration(data_time,n_bchop,band,reffreq,backendreadoutparms); islong = false; isinvalid = false; } while(i_group < grouplen - 1) { HIFISlowChopOffIntegration(data_time,n_bchop,band,reffreq,rates); // retune i_group = i_group + 1; runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen]; HIFIChangeFreq(band,runningfreq); } HIFISlowChopOffIntegration(data_time,n_bchop,band,reffreq,rates); // Now we switch to the next frequency group or repeat the cycle if(state[2] % n_cycles == 0 && i_phase == 1) { // Big tuning step, but not at end of observation if(state[2] < allsteps) { i_freqcycles = i_freqcycles + 1; runningfreq = freqgrid[grouporder[0][0] + i_freqcycles * grouplen]; target = targetnames[i_freqcycles]; HIFIRetuneFreq(band,runningfreq,target); runintostate = true; } } } // Active WBS HK if we have a nod slew without calibration if(state[2] % 2 == 0 && state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } if(state[0] == 9) { // Load nod delay(readoutdead); SScanLoadMeasurement(band,runningfreq,reffreq,retuneload,eff_resolution{0},data_time,backendreadoutparms); isinvalid = true; runintostate = false; } if(state[0] == 5) { // The instrument stops halftunelength before the telescope // but I have to wait to close the observation HIFICloseObs(); } } } {string,double,double}[] procedure HifiMappingModeLoadChopOTFSequencerInit { string modeName = "load-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = LoadChopPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities // Main loop int main_phase = iceil(phaselengths{0}); // How many lines could we do at most? int n_linesperscan_guess = main_phase / (2 * datalimit) + 1; n_linesperscan_guess = imax(n_linesperscan_guess * n_linesperscan_guess / npoints,1); // restrict the scan size if(nlines == 1 && n_linesperscan_guess > 1) { n_linesperscan_guess = 2; } else { n_linesperscan_guess = IMultiple(n_linesperscan_guess,nlines); n_linesperscan_guess = imin(n_linesperscan_guess,nlines); } int n_linesperscan_range = 1 - n_linesperscan_guess; if(n_linesperscan_range == 0) { n_linesperscan_range = 1; } double n_pointsperscan = double(n_linesperscan * npoints); // Compute back int int_time_guess = main_phase / iceil(sqrt(n_pointsperscan)); int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int n_switch_on_guess = imax(int_time_guess / (2 * data_time_guess),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } data_time_guess = imax(imin(5,int_time_guess / (2 * n_switch_on_guess)),datalimit); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * 0.67 * sqrt(n_pointsperscan) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_linesperscan",double(n_linesperscan_guess),double(n_linesperscan_range)}]; return retvalues; } // Get maximum delay needed for backend readout after FastChopSpectroscopy int procedure FastChopReadoutDelay { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{true,1,[true,true,true,true]},{true,1,[true,true,true,true]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]},{true,[[0,2048],[0,2048],[0,2048],[0,2048]]}}; // HRS1/2 {used,resolution,subbands used}, WBS1/2 {used, channel windows} }{ // Currently the delay applies independent from the spectrometer selection // if (backendreadoutparms{2}{0} || backendreadoutparms{3}{0}) { double[] dead = CalibrationReader("fastchopreadout",["fastchopreadout"],band,lo_freq); // } return iceil(dead[0]); } // Equivalent procedure for the nodding_of_raster pointing mode {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} procedure DBSMultiRaster_telescope { int naifid = 0; // Tracing object ID {double,double} mapcenter = {0.0,0.0}; // Coordinates of the center of the map {double,double} linedistance = {0.0050,0.0050}; // Distance between subsequent rows double stepsize = 0.0050; // Distance between subsequent points in the raster line int nlines_tot = 1; // Number of rows in the map; int npoints = 10; // Number of points per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string throw = ""; // Identifier for chop throw, empty is standard {int,int,int,int,int,int,int,int,int,int,int,int,int} timing = {4,10,4,21,1,1800,0,10,1,1,1,50,0}; // full timing parameter list int n_cycles = 1; // Number of half OFF-ON-ON-OFF pointing cycles }{ // Assign values int pointing = timing{1}; int loadlength = timing{3}; int n_loadinterval = timing{7}; int n_pointsperscan = timing{10}; int initlength = timing{11}; int dangling = timing{12}; // Create variables for telescope command string ib = GetBoresight(band,lo_freq,true); // A change of ra-dec depending on naifid may be needed double ra = mapcenter{0}; double dec = mapcenter{1}; double patt = AngleFromVector(linedistance); patt = RotateRight(patt); // Pattern angle and throw of the chopper direction // The nodding angle should always be parallel to the chopper double[] chopper = GetSkyChopThrow(band,lo_freq,throw); double nodlength = chopper[0]; double pattnod = chopper[1]; nodlength = max(nodlength * 3600.0,2.0); // Map always in sky coordinates, // (nod is always in instrument coordinates by default) bool fixed = true; // Map parameters double rowstep = 0.5 / 3600.0; double d1 = double(iceil(stepsize / rowstep)) * rowstep * 3600.0; double linestep = 0.5 / 3600.0; double d2 = AngleVectorLength(linedistance); d2 = double(iceil(d2 / linestep)) * linestep * 3600.0; // Exception for the "impossible" case of spacings below 2arcsec d1 = max(d1,2.0); d2 = max(d2,2.0); // no load slew if period too long if(n_loadinterval > npoints * nlines_tot * n_cycles / n_pointsperscan) { n_loadinterval = 0; } // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(pointing < 10) { SError("Pointing phase length too short. Increase the number of integrations."); } if(nodlength > 960.0) { IError("Nodding length too long. Choose a smaller chop throw."); } if(d1 > 480.0) { IError("Raster point spacing too coarse. Increase the sampling."); } if(d2 > 480.0) { IError("Raster line spacing too coarse. Increase the sampling."); } // repetition at multiple frequencies not yet implemented: int trep = 0; int n_repeat = 1; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,fixed,patt,0.0,0.0,npoints,nlines_tot,d1,d2,pointing,trep,pattnod,nodlength,n_cycles,n_pointsperscan,n_repeat,loadlength,n_loadinterval}; } //////////////////////////////////// // Routine to provide initial guesses for sequence parameters // Position switch observing mode // {string,double,double}[] procedure HifiPointProcPositionSwitchSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,5]; // data dump interval limited by the data rates int n_int_on = 3 in [2,1800]; // number of data dumps for integration per phase int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int int_time_guess = imax(iceil(0.3 * allan_time_lores),datalimit); int data_time_guess = imin(5,int_time_guess); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_int_on_guess = imax(int_time_guess / data_time_guess,2); int n_int_on_range = 2 - n_int_on_guess; if(n_int_on_range == 0) { n_int_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,n_int_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Contruct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)}]; return retvalues; } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for a // Spectral Scan Frequency-Switch observing mode // // We assume that each telescope motion is related to an // instrument calibration. // {{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} procedure SScanFSwitch_pre_timing { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_chop_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_chop_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Create composite readout structure for backends {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get frequency grid characteristic parameters {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq_low,lo_freq_up,redundancy,freq_throw,n_freq_point); double reffreq = fqparms{1}; double[] freqgrid = fqparms{2}; int[][] grouporder = fqparms{3}; // Process tuning level grid double[][] levelgrid = GetSScanLevelGrid(band,wbs1,wbs2,freqgrid,fqparms{0},grouporder); {bool,double[]} targets = TargetLevels(band,reffreq,levelgrid); bool retuning = targets{0}; double[] targetgrid = targets{1}; string reftarget = ""; if(retuning) { reftarget = "sscan_normal"; } {int,double,double[],int[][],bool,double[],int,bool} spectralparms = {fqparms{0},reffreq,freqgrid,grouporder,retuning,targetgrid,fqparms{4},fqparms{5}}; ////////////////////////////////////////////////////////////////////// // Get timing within the normal frequency-switch observations // Compute load integration time int loadlength = duration(SScanDoubleLoadMeasurement(band,reffreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); loadlength = loadlength + readoutdead; int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int jitterdead = GetMaxTimeJitter(band,reffreq); // Integration time per frequency and pointing int on_inttime = 2 * n_chop_on * data_time; int off_inttime = 2 * n_chop_off * data_time_off; // Duration of initial set up // Staying at the same frequency makes no sense here. // First frequency point double runningfreq = freqgrid[grouporder[1][0]]; // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFIFsw(band,runningfreq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,runningfreq,true); } initlength = initlength + loadlength; // Tuning delays int bigtunestep = duration(HIFIRetuneFsw(band,reffreq,freq_throw,reftarget)); // Correct for variation within the band int tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq); bigtunestep = bigtunestep + 2 * tunediff; // As step within a group could be faster than a large step if(n_freq_point > 1) { int smallstep = duration(HIFIChangeFreqFsw(band,reffreq,freq_throw)); } else { smallstep = bigtunestep; } // For double phases I can use the added jitterdead in both phases for tune int auxtunestep = bigtunestep - jitterdead; int halftunestep = (auxtunestep + 1) / 2; // Telescope pointing int on_pointing = n_freq_point * on_inttime + (n_freq_point - 1) * smallstep + halftunestep + jitterdead; int off_pointing = off_inttime + halftunestep + jitterdead; // Check load_interval allowance int scan_time = 2 * imax(on_pointing,off_pointing); if(scan_time > load_spacing) { SError("Load interval of " + load_interval + "s is exceeded by " + n_chop_on * n_freq_point + " chop cycles."); } // Estimate of the load-cycles to issue a representative // telescope command if(n_cycles > 1) { // How often do I have to perform a load slew int n_loadinterval = imax(load_interval / scan_time,1); // fit with n_cycles n_loadinterval = imin(n_loadinterval,n_cycles); n_loadinterval = IMultiple(n_loadinterval,n_cycles); } else { n_loadinterval = 1; } // recompute load length during slews in case of short integrations // This regime must be maintained in the post_timing if(n_loadinterval <= 1) { loadlength = duration(SScanDoubleLoadMeasurement(band,reffreq,reffreq,freq_throw,false,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; } // No dangling needed in this mode - we stop halftunelength before telescope int dangling = 0; bool end_load_on = false; bool end_load_off = false; // Return all the times needed for telescope call and post_timing processing return {{on_inttime,off_inttime,on_pointing,off_pointing,loadlength,auxtunestep,load_spacing,n_loadinterval,n_chop_on,n_chop_off,data_time,data_time_off,end_load_on,end_load_off,initlength,dangling},spectralparms}; } ///////////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the OTF observing mode {double,double,double,double,double} procedure OTFLoadChop_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int nlines_tot = 1; // Number of rows in the map int data_time = 4; // chunk size given by the data rates and optimum speed int n_switch_on = 1; // Supersamplingfactor int n_linesperscan = 2; // Number of lines between two OFFs int off_inttime = 16; // Integration time per OFF phase int n_cycles = 1; // Number of map coverages double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ // The sum of drift noise and radiometric noise is computed. // double tdead = tact{0}; // Average total dead time in one scan double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase double deadtimeperonphase = tact{3}; // Dead time per switch phase on ON // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Differential Allan variance allanparms = InterpolateSpecLChopAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double dallan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // resolution of OFF phase double sw_resolution = GetLoadChopSWResolution(band,lo_freq); double sw_resolution_lores = max(eff_resolution{1},sw_resolution); double sw_resolution_hires = max(eff_resolution{0},sw_resolution); // !!!! The computation of the noise is formally NOT CORRECT for this // !!!! case. For simplicity we use as a rough approximations the equations // !!!! for a double-difference setup instead of a difference with // !!!! OTF scheme !!! // Compute the relative noise for the detailed timing double on_int = double(2 * data_time * n_switch_on); // correct for double scan - treat like integrated in one go if(nlines_tot == 1 && n_linesperscan > 1) { on_int = on_int * double(n_linesperscan); } // fudge factor to taking OFF interpolation into account double off_int = double(off_inttime) * 1.5; // The dead time per switch might deviate between ON and OFF - ignored double deadtimeperswitch = deadtimeperonphase; // Dead time includes other points, but excludes off_int fudging // This is slightly too small (excludes inner point dead time) - ignored double tdiff = max(tscan - on_int - off_int,0.0); // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = DoubleDifferenceNoise(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdiff / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); double systemnoise_hires = DoubleDifferenceNoise(inttimeperonphase / allan_time_hires,[inttimeperoffphase / inttimeperonphase,sw_resolution_hires / eff_resolution{0},on_int / allan_time_hires,off_int / allan_time_hires,deadtimeperswitch / allan_time_hires,tdiff / allan_time_hires,alpha,dallan_time_hires / allan_time_hires,dalpha]); double noiseratio = DoubleDifferenceNoiseRatio(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdiff / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 1000000.0 * double(n_cycles) * tscan)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 1000000.0 * double(n_cycles) * tscan)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command for the OTF observing mode {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,int} procedure OTFDoubleChopNoRef_telescope { int naifid = 0; // Tracking object ID {double,double} mapcenter = {0.0,0.0}; // Coordinates of the center of the map {double,double} linedistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1; // Number of rows in the map double linesize = 0.0050 in [0.0,2.0]; // Length of OTF lines double scanvelocity = 4.0E-4 in [2.75E-5,0.017]; // Scan velocity in ? per s string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int n_cover = 1; // Number of map coverages {int,int,int,int,bool,int,int} timing = {21,1780,1,21,false,50,0}; // timing parameter list }{ // Assign values int holdlength = timing{3}; // Load duration - turn around time int n_loadinterval = timing{2}; // N of OTF scans between load measurements int initlength = timing{5}; // Initial setup time int dangling = timing{6}; // Final load measurement // no load means n_loadinterval=0 here int nlines_tot = nlines * n_cover; if(n_loadinterval > nlines_tot) { int n_linesperscan = 0; } else { n_linesperscan = n_loadinterval; } // Create variables for telescope command string ib = GetBoresight(band,lo_freq,false); double ra = mapcenter{0}; double dec = mapcenter{1}; double patt = AngleFromVector(linedistance); patt = RotateRight(patt); // I assume that ValidMapSize was called, so that the API granularity // is meet for d1 and rate double d1 = linesize * 3600.0; double rate = scanvelocity * 3600.0; // Granularity for d2 double linestep = 0.5; double d2_req = AngleVectorLength(linedistance); d2_req = d2_req * 3600.0; // Define maximum reduction double eps = 0.98; double d2 = double(iceil(d2_req * eps / linestep)) * linestep; // Exception for the "impossible" case of spacings below 2arcsec d2 = max(d2,2.0); // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(rate > 60.0) { IError("Maximum scan velocity exceeded. Reduce the step size."); } else { if(rate < 0.1) { SError("Minimum scan velocity not reached. Reduce switch cycle number."); } } if(d1 > 7200.0) { IError("OTF line length too long. Reduce the map size."); } if(d2 > 480.0) { IError("OTF line spacing too coarse. Increase the sampling."); } // repetition at multiple frequencies not yet implemented: int n_repeat = n_cover; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,true,patt,0.0,0.0,nlines,d1,d2,rate,holdlength,n_linesperscan,n_repeat}; } ///////////////////////////////////////////////////////////////// // Procedures to compute the WBS IF levels for spectral scans // // Read attenuators settings across a spectral scan double[][] procedure GetSScanLevels { string band = "4a"; // HIFI band double[] freqgrid = [978053.7,978301.8,978381.1]; // frequency grid int[] subbandindices = [0,1,2,3,4,5,6,7]; // WBS subbands actually used }{ // Go select subband attenuators to read string[] subbandnames = ["pow_hw1","pow_hw2","pow_hw3","pow_hw4","pow_vw1","pow_vw2","pow_vw3","pow_vw4"]; int nsub = length(subbandindices); string[] bandnames = []; for(int j = 0 .. nsub - 1) { bandnames[j] = subbandnames[subbandindices[j]]; } // Initialize output grid double[][] attgrid = [[]]; double[] hlpgrid = []; int nel = length(freqgrid); // Go through frequency grid and read attenuators for(int i = 0 .. nel - 1) { double lo_freq = freqgrid[i]; double[] atts = CalibrationReader("power_levels",bandnames,band,lo_freq); attgrid[i] = clone(atts); } return attgrid; } {int,double,double,double,double,double} obs HifiSScanModeDBS { string modeName = "freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-SScan-DBS",{data_time,0,0,n_switch_on,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,bool,int,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanDBS_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,n_switch_on,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},double,double,double} post_timing = SScanDBS_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int n_loadinterval = post_timing{1}{7}; int n_bchop = post_timing{1}{8}; int shiftlength = post_timing{1}{10}; int initlength = post_timing{1}{11}; double avnumchop = post_timing{2}; // efficiency parameters double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanDBS_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_cycles,n_total,n_bchop,n_switch_on,n_loadinterval,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SScanDBS_deadtimes(band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,n_bchop,n_switch_on,n_cycles,avnumchop,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = SScanDBS_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,continuumDetection,n_cycles,tscan,tact); // Evaluate performance SScanDBS_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_total,groupnumber * n_freq_point,avnumchop,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the DBS raster mode procedure JupiterFastDBSRaster_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 10 in [4,80]; // data dump interval int n_int = 20; // number chop cycles to integrate in ICU before transfer int n_seq = 1; // number of data transfer cycles per pointing int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles int n_pointsperscan = 1; // Number of points measured before moving to the second pointing phase int n_loadinterval = 10; // number of nods before a load measurement int n_load = 0; // additional load measurements in one pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,0,10,20,21,0,0,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration bool iscross = false; // Whether we use a cross instead of a raster }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Fixed timings in the fast-chop mode int load_datatime = GetStdLoadReadout(band,lo_freq); // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time / 2); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,true); int readoutdead = FastChopReadoutDelay(band,lo_freq,backendreadoutparms); // There is no nod counter in the return values - count this by hand int inod = 0; // Do I have to make loads in short nods and subsequent holds? if(iscross) { bool holdforload = n_pointsperscan > 1; } else { holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles; } //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; int[] choppars = [2 * n_int,0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"jupiter"); } delay(tinitslew - (time() - startobs) - hkduration - loadlength); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles // The use of n_load differs by 1 from the other observing modes here for(int i1 = 1 .. n_load - 1) { HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle - no load HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: // n_pointsperscan=1, n_loadinterval > n_cycles if(state[3] % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } } // Second pointing phase if(state[0] == 7) { // second nod position choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); for(int i2 = 1 .. n_load - 1) { HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); choppars = HIFIConfigureFastChopIntegration(data_time,n_int,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: if(state[3] % 2 == 0) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } } // Load nod if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); runintostate = false; } // Hold if(state[0] == 6) { // finished shift of instrument operations relative to pointing command runintostate = false; } // Final load if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } ////////////////////////////////////////////////////////////////////////// // Procedure to generate the telescope command for the OTF observing mode {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} procedure OTFmap_telescope { int naifid = 0; // Tracking object ID {double,double} mapcenter = {0.0,0.0}; // Coordinates of the center of the map {double,double} linedistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines_tot = 1; // Number of rows in the map double linesize = 0.0050 in [0.0,2.0]; // Length of OTF lines {double,double} offposition = {0.2,0.2}; // Coordinates of the OFF position double scanvelocity = 4.0E-4 in [2.75E-5,0.017]; // Scan velocity in ? per s string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int n_linesperscan = 1; // Number of lines between two OFFs int n_cover = 1; // Number of map coverages {int,int,int,int,int,int,int,int} timing = {10,1,12,13,21,10,50,0}; // timing parameter list }{ // Assign values int off_inttime = timing{3}; // Length of OFF integration int loadlength = timing{4}; // Load duration int n_loadinterval = timing{5}; // N of OTF scans between load measurements int initlength = timing{6}; // Initial setup time int dangling = timing{7}; // Final hold // Create variables for telescope command string ib = GetBoresight(band,lo_freq,false); // A change of ra-dec depending on naifid may be needed double ra = mapcenter{0}; double dec = mapcenter{1}; double raoff = offposition{0}; double decoff = offposition{1}; double patt = AngleFromVector(linedistance); patt = RotateRight(patt); // I assume that ValidMapSize was called, so that the API granularity // is meet for d1 and rate (should rather be done in HSPOT) double d1 = linesize * 3600.0; double rate = scanvelocity * 3600.0; // Separate treatment of repeated scans of the same line if(nlines_tot == 1) { int n_lines_eff = n_linesperscan; double d2 = 0.0; } else { n_lines_eff = nlines_tot; // Granularity for d2 double linestep = 0.5; double d2_req = AngleVectorLength(linedistance); d2_req = d2_req * 3600.0; // Define maximum reduction double eps = 0.98; d2 = double(iceil(d2_req * eps / linestep)) * linestep; // Exception for the "impossible" case of spacings below 2arcsec d2 = max(d2,2.0); } // Check parameter compatibility with pointing command for parameters // which are no direct input parameters if(rate > 60.0) { IError("Maximum scan velocity exceeded. Reduce the step size."); } else { if(rate < 0.1) { SError("Minimum scan velocity not reached. Reduce the supersampling."); } } if(d1 > 7200.0) { IError("OTF line length too long. Reduce the map size."); } if(d2 > 480.0) { IError("OTF line spacing too coarse. Increase the sampling."); } // We already put harder constrains on some parameters than required // by the pointing commands: // n_lines_eff <= 240 (HIFI), <= 1500(MPS) // n_linesperscan*j = n_lines_eff (HIFI), n_linesperscan <= n_lines_eff (MPS) // // repetition at multiple frequencies not yet implemented: int thold = 0; int nhold = 0; int n_repeat = n_cover; // return parameters in required order return {initlength,0,dangling,ib,naifid,ra,dec,true,patt,0.0,0.0,n_lines_eff,d1,d2,rate,n_linesperscan,off_inttime,raoff,decoff,n_repeat,thold,nhold,loadlength,n_loadinterval}; } ///////////////////////////////////////////////////////////////////////////// // procedure needed for LO tuning ///////////////////////////////////////////////////////////////////////////// //General LO configuration command procedure HIFI_Configure_LCU_proc_aot { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978.2; //LO frequency int freq_nx = 0; // HL_freq_nx int lsu_main = 0; // HL_LSU_main int lsu_offset = 0; // HL_LSU_offset int d2_step = 1; // HL_D2_step double plevel_v = 0.0; double m1_v = 9.0; double m2_v = -2.0; double m3_v = 0.0; double gate1_v = -2.5; double gate2_v = -2.5; double drain1_v = 2.8; string curlim1_v = "1.4"; double drain2_v = 2.6; string curlim2_v = "1.4"; int macro_checksum = 0; // HL_macro_checksum int config_lo_delay = 6; }{ //Check that Vd2 is within the blue limits drain2_v = Check_BLUE_LIMIT_D2_proc_fm(band,lo_freq,drain2_v); // // //Execute configuration //Check which LO band is used if(band == "1a") { //Band 1a Hifi_HIFI_Conf_safe_LCU_ch1a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "1b") { //Band 1b Hifi_HIFI_Conf_safe_LCU_ch1b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "2a") { //Band 2a Hifi_HIFI_Conf_safe_LCU_ch2a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "2b") { //Band 2b Hifi_HIFI_Conf_safe_LCU_ch2b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "3a") { //Band 3a Hifi_HIFI_Conf_safe_LCU_ch3a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "3b") { //Band 3b Hifi_HIFI_Conf_safe_LCU_ch3b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "4a") { //Band 4a Hifi_HIFI_Conf_safe_LCU_ch4a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "4b") { //Band 4b Hifi_HIFI_Conf_safe_LCU_ch4b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum); } if(band == "5a") { //Band 5a Hifi_HIFI_Conf_nom_LCU_ch5a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "5b") { //Band 5b Hifi_HIFI_Conf_nom_LCU_ch5b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "6a") { //Band 6a Hifi_HIFI_Conf_nom_LCU_ch6a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "6b") { //Band 6b Hifi_HIFI_Conf_nom_LCU_ch6b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "7a") { //Band 7a Hifi_HIFI_Conf_nom_LCU_ch7a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } if(band == "7b") { //Band 7b Hifi_HIFI_Conf_nom_LCU_ch7b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v,macro_checksum); } // delay(config_lo_delay); // //Read TM pages and clear error flags LCU_Read_TM_pages_proc_aot(); } // Slow chop procedure HIFI_Spectr_slow_chop_proc_aot { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // chop cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz string[] phases = ["chop_M3left","chop_M3right"]; // identifiers for chopper positions double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ //Get appropriate chopper voltages {bool,double,double} chopparms = GetChopVoltages(band,lo_freq,phases[0],phases[1]); bool isPrime = chopparms{0}; // set data rates non_ess_hk_data_rate(rates[2] / 1024.0); data_rate(rates[0] / 1024.0); // Call command if(isPrime) { Hifi_HIFI_P_Spectr_slow_chop($BBID,chopparms{1},chopparms{2}); } else { Hifi_HIFI_R_Spectr_slow_chop($BBID,chopparms{1},chopparms{2}); } delay(2 * n_cycle * data_time); // reset data rates non_ess_hk_data_rate(rates[1] / 1024.0); data_rate(0.0); } //Retune HIFI for frequency switch - keep magnet and backends procedure HIFITuneFreqFsw { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq_1 = 978200.0; //LO frequency for FSW1 phase double lo_freq_2 = 978300.0; //LO frequency for FSW2 phase bool newsetting = true; // whether LSU/LOU parameters are new string target_name = "sscan_normal"; // Name of target level }{ //LO power tuning: could use either H or V polar {double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq_1); double x = result[0]{0}; string tuningbackend = "H"; if(iround(x) == 2) { tuningbackend = "V"; } else { tuningbackend = "H"; } // All tuning for first frequency, and store in FSW1 register double lo_freq_setting = 0.5 * (lo_freq_1 / 1000.0 + lo_freq_2 / 1000.0); LO_tuning_block_aot(band,lo_freq_1 / 1000.0,lo_freq_setting,tuningbackend,newsetting,newsetting,true); // //Spectrometer attenuator tuning - on the sky or cold load if(target_name != "") { WBS_attenuators_block(band,lo_freq_1 / 1000.0,target_name,true); } // // Second frequency setup, and stored in FSW2 register LO_tuning_block_aot(band,lo_freq_2 / 1000.0,lo_freq_setting,tuningbackend,false,newsetting,true); // } // HRS partial configuration SPECIFIC TO AOT CUS, block // Configures the LO and attenuators block HRS_config_att_lo_block_aot HIFI 6624 { string band = "4a"; // HIFI band string[] hrs_mode = ["mr","mr"]; //HRS resolution code double[] hrsH_LO = [4.5,5.5,6.5,7.5]; //IF position of HRS-H sub-bands double[] hrsV_LO = [4.5,5.5,6.5,7.5]; //IF position of HRS-V sub-bands }{ // Fetch HRS configuration parameters //=================================== //H-polar string hrs_filename_h = "name_confighrs_" + hrs_mode[0]; {double,string}[] result = ConfigurationReader(hrs_filename_h,["hrh_switch","hrh_1u_att","hrh_1l_att","hrh_2u_att","hrh_2l_att","hrh_3u_att","hrh_3l_att","hrh_4u_att","hrh_4l_att","hrh_down_ol5","hrh_down_ol6","hrh_down_ol7"],band,0.0); string hrs_polarization_h = result[0]{1}; double hrsH_ATT_U1 = result[1]{0}; double hrsH_ATT_L1 = result[2]{0}; double hrsH_ATT_U2 = result[3]{0}; double hrsH_ATT_L2 = result[4]{0}; double hrsH_ATT_U3 = result[5]{0}; double hrsH_ATT_L3 = result[6]{0}; double hrsH_ATT_U4 = result[7]{0}; double hrsH_ATT_L4 = result[8]{0}; double[] hrsH_LO_total = [hrsH_LO[0],hrsH_LO[1],hrsH_LO[2],hrsH_LO[3],result[9]{0},result[10]{0},result[11]{0}]; //V-polar string hrs_filename_v = "name_confighrs_" + hrs_mode[1]; result = ConfigurationReader(hrs_filename_v,["hrv_switch","hrv_1u_att","hrv_1l_att","hrv_2u_att","hrv_2l_att","hrv_3u_att","hrv_3l_att","hrv_4u_att","hrv_4l_att","hrv_down_ol5","hrv_down_ol6","hrv_down_ol7"],band,0.0); string hrs_polarization_v = result[0]{1}; double hrsV_ATT_U1 = result[1]{0}; double hrsV_ATT_L1 = result[2]{0}; double hrsV_ATT_U2 = result[3]{0}; double hrsV_ATT_L2 = result[4]{0}; double hrsV_ATT_U3 = result[5]{0}; double hrsV_ATT_L3 = result[6]{0}; double hrsV_ATT_U4 = result[7]{0}; double hrsV_ATT_L4 = result[8]{0}; double[] hrsV_LO_total = [hrsV_LO[0],hrsV_LO[1],hrsV_LO[2],hrsV_LO[3],result[9]{0},result[10]{0},result[11]{0}]; // result = ConfigurationReader("name_delays",["hrs_config_delay"],band,0.0); int hrs_config_delay = iround(result[0]{0}); // //Convert IF frequencies into A and M parameters int[] a_m_parameter = ComputeA_M_parameters(hrs_mode,hrsH_LO_total[0],hrsH_LO_total[1],hrsH_LO_total[2],hrsH_LO_total[3],hrsH_LO_total[4],hrsH_LO_total[5],hrsH_LO_total[6],hrsV_LO_total[0],hrsV_LO_total[1],hrsV_LO_total[2],hrsV_LO_total[3],hrsV_LO_total[4],hrsV_LO_total[5],hrsV_LO_total[6]); //H-polar int hrsH_LO1_M = a_m_parameter[1]; int hrsH_LO1_A = a_m_parameter[0]; int hrsH_LO2_M = a_m_parameter[3]; int hrsH_LO2_A = a_m_parameter[2]; int hrsH_LO3_M = a_m_parameter[5]; int hrsH_LO3_A = a_m_parameter[4]; int hrsH_LO4_M = a_m_parameter[7]; int hrsH_LO4_A = a_m_parameter[6]; int hrsH_LO5_M = a_m_parameter[9]; int hrsH_LO5_A = a_m_parameter[8]; int hrsH_LO6_M = a_m_parameter[11]; int hrsH_LO6_A = a_m_parameter[10]; int hrsH_LO7_M = a_m_parameter[12]; Hifi_HIFI_Config_HRS_H_att_lo($BBID,hrs_polarization_h,hrsH_ATT_U1,hrsH_ATT_L1,hrsH_ATT_U2,hrsH_ATT_L2,hrsH_ATT_U3,hrsH_ATT_L3,hrsH_ATT_U4,hrsH_ATT_L4,hrsH_LO1_M,hrsH_LO1_A,hrsH_LO2_M,hrsH_LO2_A,hrsH_LO3_M,hrsH_LO3_A,hrsH_LO4_M,hrsH_LO4_A,hrsH_LO5_M,hrsH_LO5_A,hrsH_LO6_M,hrsH_LO6_A,hrsH_LO7_M); // //delay(hrs_config_delay); //V-polar int hrsV_LO1_M = a_m_parameter[14]; int hrsV_LO1_A = a_m_parameter[13]; int hrsV_LO2_M = a_m_parameter[16]; int hrsV_LO2_A = a_m_parameter[15]; int hrsV_LO3_M = a_m_parameter[18]; int hrsV_LO3_A = a_m_parameter[17]; int hrsV_LO4_M = a_m_parameter[20]; int hrsV_LO4_A = a_m_parameter[19]; int hrsV_LO5_M = a_m_parameter[22]; int hrsV_LO5_A = a_m_parameter[21]; int hrsV_LO6_M = a_m_parameter[24]; int hrsV_LO6_A = a_m_parameter[23]; int hrsV_LO7_M = a_m_parameter[25]; Hifi_HIFI_Config_HRS_V_att_lo($BBID,hrs_polarization_v,hrsV_ATT_U1,hrsV_ATT_L1,hrsV_ATT_U2,hrsV_ATT_L2,hrsV_ATT_U3,hrsV_ATT_L3,hrsV_ATT_U4,hrsV_ATT_L4,hrsV_LO1_M,hrsV_LO1_A,hrsV_LO2_M,hrsV_LO2_A,hrsV_LO3_M,hrsV_LO3_A,hrsV_LO4_M,hrsV_LO4_A,hrsV_LO5_M,hrsV_LO5_A,hrsV_LO6_M,hrsV_LO6_A,hrsV_LO7_M); // delay(hrs_config_delay); } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of peakup observing mode {int,{int,int,int,int,int,double,int,int}} procedure Peakup_post_timing { {int,int,int,int,int,double,int,int} pre_timing = {8,10,2,21,4,1.6,50,0}; // pre timing parameter list int[] telescopetimes = [300,180,10,10,29,0]; int nlines_tot = 3; // Number of rows in the map int npoints = 3; // Number of points per row }{ // Get all values from the pre_timing section int inttime = pre_timing{0}; int pointing = pre_timing{1}; int data_time = pre_timing{2}; int loadlength = pre_timing{3}; int n_chop = pre_timing{4}; double eff_resolution = pre_timing{5}; int initlength = pre_timing{6}; int dangling = pre_timing{7}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int slewtime = telescopetimes[2]; // Slew time to next point int slewline = telescopetimes[3]; int tend = telescopetimes[5]; // Total number of scans int n_tot = npoints * nlines_tot; /////////////////////// // obtain all slew durations int tinlinesdead = (npoints - 1) * slewtime * nlines_tot; int toutlinesdead = (nlines_tot - 1) * slewline; // Compute total duration int totaltime = n_tot * pointing + tinlinesdead + toutlinesdead; // Add dangling time if not included in pointing // Add time needed to perform AOCS correction int closelength = duration(HIFICloseObs()) + duration(HifiPeakupCorrection()); dangling = imax(dangling + closelength - tend,0); totaltime = totaltime + dangling + tend; // show gyro-propagation messages GCPMessages(pointing,totaltime,tend); // Return all the times needed in the observing mode modules return {totaltime,{inttime,pointing,data_time,loadlength,n_chop,eff_resolution,initlength,dangling}}; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the DBS raster mode procedure DBSRaster_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_seq = 1; // Number of continuous chop cycles int n_cycles = 1; // Number of half OFF-ON-ON-OFF cycles int n_pointsperscan = 1; // Number of points measured before moving to the second pointing phase int n_loadinterval = 10; // number of nods before a load measurement int n_load = 0; // additional load measurements in one pointing phase bool final_load = false; // Need for final load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,10,0,10,20,21,0,0,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration bool iscross = false; // Whether we use a cross instead of a raster }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get all values from the telescope section int tinitslew = telescopetimes[1]; // Initial slew time //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Count phases by hand to allow simultaneous usage by Raster and Cross int iphase = 0; // There is no nod counter in the return values - count this by hand int inod = 0; // Do I have to make loads in short nods and subsequent holds? if(iscross) { bool holdforload = n_pointsperscan > 1; } else { holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles; } //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; bool runintostate = false; while(state[0] >= 0) { if(runintostate) { state = next_state_no_check(); } else { state = next_state(); } if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; iphase = iphase + 1; } ////////////////////////////////////////////////////////////////////// // States for actual observations if(state[0] == 3) { // First nodding position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); // Loop for load cycles // The use of n_load differs by 1 from the other observing modes here for(int i1 = 1 .. n_load - 1) { HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFISlowChopOnIntegration(data_time,n_seq,band,lo_freq,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: // n_pointsperscan=1, n_loadinterval > n_cycles if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } // Update phase counter iphase = iphase + 1; } // Second pointing phase if(state[0] == 7) { // second nod position HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); for(int i2 = 1 .. n_load - 1) { HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Perform load calibration delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFIConfigureSlowChopIntegration(data_time,n_seq,band,lo_freq,backendreadoutparms); } // Last cycle HIFISlowChopOffIntegration(data_time,n_seq,band,lo_freq,rates); // Load measurement if required - time included in pointing if(n_load > 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } // Final point before nod // Special treatment for all cases where load has to be replaced by hold: if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) { inod = inod + 1; if(holdforload && inod % n_loadinterval == 0 && n_load == 0) { delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = true; } } else { // keep shift if we come from a holdforload nod, otherwise reset if(!holdforload) { runintostate = false; } } // Update phase counter iphase = iphase + 1; } // Load nod if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); runintostate = false; } // Hold if(state[0] == 6) { // finished shift of instrument operations relative to pointing command runintostate = false; } // Final load if(state[0] == 5) { delay(readoutdead); if(final_load) { // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } runintostate = false; HIFICloseObs(); } } } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure FastDBS_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval int n_int = 20; // number of integrations in one data dump interval int n_data = 3; // number of subsequent readouts int n_load = 0; // number of integrations in one pointing phase -1 double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute parameters for the instrument timing {double,double} tinst = GetInstDeadFastChop(data_time,n_int,n_data,band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * n_data) - tinst{0}; // subtract dead times in switches // only half of them are subtracted due to ABAB scheme tdeadint = tdeadint - double(n_int * n_data) * tinst{1}; // Total dead time per cycle double tdead_tot = tdead + double(2 * (n_load + 1)) * tdeadint; // Integration time double tphaseint = tinst{0} / double(2 * n_int * n_data); return {tdead_tot,tphaseint,tinst{1}}; } //////////////////////////////////// // Routines to provide initial guesses for sequence parameters //////////////////////////////////// // Frequency switch observing mode // {string,double,double}[] procedure HifiPointProcFSwitchSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_switch_off = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = FSwitchPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_guess = imax(iceil(phaselengths{0} / (2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; new_data_time = MatchMinPointing(data_time_off_guess,data_time_off_range,2 * n_switch_off_guess); data_time_off_guess = new_data_time{0}; data_time_off_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)}]; return retvalues; } ///////////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the OTF observing mode {double,double,double,double,double} procedure OTFFSwitch_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int nlines_tot = 1; // Number of rows in the map int data_time = 4; // chunk size given by the data rates and optimum speed int n_switch_on = 1; // Supersamplingfactor int n_linesperscan = 2; // Number of lines between two OFFs int off_inttime = 16; // Integration time per OFF phase int n_cycles = 1; // Number of map coverages double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ // The sum of drift noise and radiometric noise is computed. // double tdead = tact{0}; // Average total dead time in one scan double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase double deadtimeperonphase = tact{3}; // Dead time per switch phase on ON // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Differential Allan variance allanparms = InterpolateSpecFSwitchAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double dallan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // resolution of OFF phase double sw_resolution = GetFSwitchSWResolution(band,lo_freq); double sw_resolution_lores = max(eff_resolution{1},sw_resolution); double sw_resolution_hires = max(eff_resolution{0},sw_resolution); // !!!! The computation of the noise is formally NOT CORRECT for this // !!!! case. For simplicity we use as a rough approximations the equations // !!!! for a double-difference setup instead of a difference with // !!!! OTF scheme !!! // Compute the relative noise for the detailed timing double on_int = double(2 * data_time * n_switch_on); // correct for double scan - treat like integrated in one go if(nlines_tot == 1 && n_linesperscan > 1) { on_int = on_int * double(n_linesperscan); } // fudge factor to taking OFF interpolation into account double off_int = double(off_inttime) * 1.5; // The dead time per switch might deviate between ON and OFF - ignored double deadtimeperswitch = deadtimeperonphase; // Dead time includes other points, but excludes off_int fudging // This is slightly too small (excludes inner point dead time) - ignored double tdiff = max(tscan - on_int - off_int,0.0); // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = DoubleDifferenceNoise(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdiff / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); double systemnoise_hires = DoubleDifferenceNoise(inttimeperonphase / allan_time_hires,[inttimeperoffphase / inttimeperonphase,sw_resolution_hires / eff_resolution{0},on_int / allan_time_hires,off_int / allan_time_hires,deadtimeperswitch / allan_time_hires,tdiff / allan_time_hires,alpha,dallan_time_hires / allan_time_hires,dalpha]); double noiseratio = DoubleDifferenceNoiseRatio(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdiff / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); // Compute total double sideband noise // Correct for signal in both pases double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 2000000.0 * double(n_cycles) * tscan)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 2000000.0 * double(n_cycles) * tscan)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } // Get main beam size for message double procedure GetMainBeamSize { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] fwhm = CalibrationReader("beam",["resolution"],band,lo_freq); return fwhm[0]; } {int,double,double,double,double,double} obs HifiMappingModeFSwitchOTF { string modeName = "fs-raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-FSwitch-OTF",{data_time,data_time_off,0,n_switch_on,n_switch_off,n_linesperscan,0,0,n_cycles,load_interval}); // Auxiliary routine for API parameter correction {double,double,int} mapused = ValidMapSize(band,lo_freq,lineDistance,nlines,stepsize,npoints,2 * data_time * n_switch_on); double line_used = mapused{0}; double scanvelocity = mapused{1}; int npoints_used = mapused{2}; // Call first part of the timing computer {int,int,int,int,int,int,int,int} pre_timing = OTFFSwitch_pre_timing(nlines,npoints_used,band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,double,double,int,int,double,double,int,int,int,int,int} tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,pre_timing); // Dummy call to spacecraft command int[] telescopetimes = line_scan_with_off_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int},double,double} post_timing = OTFmap_post_timing(pre_timing,telescopetimes,data_time,n_linesperscan,n_cycles,load_interval); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = OTFmap_telescope(naifid,onPosition,lineDistance,nlines,line_used,refPosition,scanvelocity,band,lo_freq,n_linesperscan,n_cycles,post_timing{1}); // Call telescope command telescopetimes = line_scan_with_off_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int n_pp = post_timing{1}{0}; int n_scans = post_timing{1}{1}; int off_inttime = post_timing{1}{2}; int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{5}; double tscan = post_timing{2}; double tdead = post_timing{3}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { OTFFSwitch_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,npoints_used * n_switch_on,n_switch_off,nlines * n_cycles,n_linesperscan,n_loadinterval,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double,double,double} tact = OTFDoubleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_linesperscan,n_pp,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = OTFFSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,nlines,data_time,n_switch_on,n_linesperscan,off_inttime,n_cycles,tscan,tact); // Evaluate performance OTFDoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints_used,n_switch_on,n_switch_off,n_scans,n_cycles,true,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // OTF load-chop observing mode // {string,double,double}[] procedure HifiMappingProcLoadChopOTFSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = LoadChopPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities // Main loop int main_phase = iceil(phaselengths{0}); // How many lines could we do at most? int n_linesperscan_guess = main_phase / (2 * datalimit) + 1; n_linesperscan_guess = imax(n_linesperscan_guess * n_linesperscan_guess / npoints,1); // restrict the scan size if(nlines == 1 && n_linesperscan_guess > 1) { n_linesperscan_guess = 2; } else { n_linesperscan_guess = IMultiple(n_linesperscan_guess,nlines); n_linesperscan_guess = imin(n_linesperscan_guess,nlines); } int n_linesperscan_range = 1 - n_linesperscan_guess; if(n_linesperscan_range == 0) { n_linesperscan_range = 1; } double n_pointsperscan = double(n_linesperscan * npoints); // Compute back int int_time_guess = main_phase / iceil(sqrt(n_pointsperscan)); int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int n_switch_on_guess = imax(int_time_guess / (2 * data_time_guess),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } data_time_guess = imax(imin(5,int_time_guess / (2 * n_switch_on_guess)),datalimit); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * 0.67 * sqrt(n_pointsperscan) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_linesperscan",double(n_linesperscan_guess),double(n_linesperscan_range)}]; return retvalues; } //////////////////////////////////// // Auxiliary functions // IsContained functions bool procedure StringIsContained { string x = " "; // search string string[] lot = [""]; // array to be searched }{ int nlen = length(lot); bool found = false; for(int i = 0 .. nlen - 1) { if(x == lot[i]) { found = true; } } return found; } // Switch on LO band: assumes HIFI is prime and LO is in nominal mode // This is wrapped into an engineeering obs in MTL // During the stabilization phase a normal load-chop-noref observation // is performed obs HifiEngSwitchonLO { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band }{ // temporarily moved from argument section to maintain compatibility with old // SOVT setup for phase3 bool robust = true; // whether the subsequent AOR is chopped+spectroscopic // First part - determine timing and telescope parameters // Fixed parameters int data_time = 4; // Data readout period {double,double} eff_resolution = {1.1,1.1}; // Native WBS resolution as goal resolution // Get reference frequency string keyfreqname = "keyfreq"; //this is for cold LO operations // "keyfreq" for cold LO operations // "keyfreq_dummy" for dummy LO operations // "midfreq" old approach double[] result_d = CalibrationReader("name_keyfreq",[keyfreqname],band,0.0); double lo_freq = result_d[0] * 1000.0; // Backend settings // standard routine from spectral scans {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,2,true,true,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; // Call specific pre_timing computer {int,int,int,int,int,int} pre_timing = SwitchOnLoadChop_pre_timing(band,lo_freq,eff_resolution,hr1,hr2,wb1,wb2,data_time,robust); // get parameters for fine pointing int totaltime = pre_timing{0}; // total duration for check int on_pointing = pre_timing{1}; // Pointing time int initlength = pre_timing{2}; // Initial setup time int dangling = pre_timing{3}; // Final load measurement // telescope command int[] ts = no_pointing(true,initlength,dangling,on_pointing); }{ // Second part - instrument commanding // get parameters for instrument int n_cycles1 = pre_timing{4}; int n_cycles = pre_timing{5}; // Backend settings // Create a composite readout structure {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // additional fixed parameters like in standard observing modes // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); ////////////////// // Instrument commanding sync(); int startobs = time(); // use state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 2) { // Initialization HIFIInitObs(); HIFISetHK("fast",true); // Actual switch-on // The switch will always be done at the same frequency LCU_switchon_proc_aot(band,lo_freq / 1000.0); // Initial setup and LO tuning Init_Mixing_proc_aot(band,lo_freq / 1000.0); //Deflux will do be done for bands 1 to 4 Deflux_SingleBand_proc_aot(band,lo_freq / 1000.0); // Standard backend tuning string target_name = "normal"; // Name of target level if(wb1{0} || wb2{0}) { WBS_attenuators_block(band,lo_freq / 1000.0,target_name,false); } if(hr1{0} || hr2{0}) { HRS_tune_block_aot(band); } // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 3) { // ON integration - long hot-cold measurement if(n_cycles1 > 0) { HIFI_Calibrate_hot_cold(band,lo_freq,data_time,2 * n_cycles1,backendreadoutparms,false); HIFITuneFreq(band,lo_freq,false,""); } HIFI_Calibrate_hot_cold(band,lo_freq,data_time,2 * n_cycles,backendreadoutparms,false); } if(state[0] == 5) { delay(readoutdead); // Perform final load measurement LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); HIFICloseObs(); } } // Finalize observations // consistency check int timeTaken = time() - startobs; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } // Noise estimates could be easily added, but are not done here // in the current implementation } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF observing mode {int,{int,int,int,int,bool,int,int},double,double} procedure OTFDoubleChopNoRef_post_timing { {int,int,int,int,bool,int,int} timing = {21,1780,1,21,false,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,2,2,40,10,20,0]; int nlines = 1; // Number of rows in the map int data_time = 4; // chunk size given by the data rates and optimum speed int n_cycles = 1; // Number of map coverages }{ // Get all values from the pre_timing section int loadlength = timing{0}; int load_spacing = timing{1}; int n_loadinterval = timing{2}; int lineint = timing{3}; bool end_load_on = timing{4}; int initlength = timing{5}; int dangling = timing{6}; // Get all values from the telescope section int telinit = telescopetimes[1]; // Initial slew time int tacc = telescopetimes[2]; // Acceleration towards line int tdec = telescopetimes[3]; // Deceleration from line int tturn = telescopetimes[5]; // Turn around between lines int tline = telescopetimes[4]; // Time in line int trep = telescopetimes[6]; // Time between two repetitions int tend = telescopetimes[7]; // Final deceleration time // Check the length of the telescope slew relative to the integration time if(tline < lineint) { CError("OTF scan length returned by telescope too short for instrument."); } // Now we can actually determine n_loadinterval including the overheads int lineduration = tline + tturn + imax(trep - tturn,0) / nlines; n_loadinterval = load_spacing / lineduration; if(n_loadinterval < 1) { SError("Scan duration too long for load period. " + "Reduce the number of chop cycles."); } // Make sure that load slews occur at the same position in each coverage int nlines_tot = nlines * n_cycles; n_loadinterval = IMultiple(n_loadinterval,nlines); // If no load required parameter has to be 0 if(n_loadinterval > nlines_tot) { // Determine need for final load measurement double rest = double(nlines_tot % n_loadinterval) + 0.5; end_load_on = rest > 0.5001 * double(n_loadinterval); } else { if(n_loadinterval > nlines) { n_loadinterval = nlines; } // In all these cases a final load will be made anyway in regular pattern end_load_on = false; } // Hold time needed for load // To use the state machine we waste the deceleration time // which could be used in principle for the load measurement as well int tover = imin(tturn - tdec,trep + tacc); int holdlength = imax(loadlength - tover,0); // Dangling load measurement if(end_load_on) { dangling = loadlength; } else { // whenever a load occurs we also have one at the end if(n_loadinterval <= nlines_tot) { dangling = loadlength - holdlength; } } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute duration of measurement int n_load = nlines_tot / n_loadinterval; int maptime = nlines_tot * (tline + tturn) + n_cycles * (trep + tacc + tdec - tturn) + n_load * holdlength; // Telescope dead time irelevant for mode without baseline reference double tdead = 0.0; // Cycle given by switch cycle double tscan = 2.0 * double(data_time); // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int totaltime = maptime + dangling - trep + tend; // show gyro-propagation messages // no gyro-propagation for line_scan_pointing GCPMessages(0,maptime,tend); // Return all the times needed in the observing mode modules return {totaltime,{loadlength,load_spacing,n_loadinterval,holdlength,end_load_on,initlength,dangling},tscan,tdead}; } {int,double,double,double,double,double} obs HifiSScanModeFSwitchNoRef { string modeName = "fs-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_cycles = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-SScan-FSwitch-NoReference",{data_time,0,0,0,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanFSwitchNoRef_pre_timing(band,lo_freq,lo_freq_up,redundancy,freq_throw,effResolution,hr1,hr2,wb1,wb2,data_time,n_cycles,n_freq_point,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,double,double,int} tpar = Fine_telescope(naifid,onPosition,band,reffreq,pre_timing{0}); // Dummy call to spacecraft command int[] telescopetimes = basic_fine_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,bool,int,int},double,double} post_timing = SScanChopNoRef_post_timing(pre_timing{0},telescopetimes); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = Fine_telescope(naifid,onPosition,band,reffreq,post_timing{1}); // Call telescope command telescopetimes = basic_fine_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9}); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int loadlength = post_timing{1}{2}; int n_per_on = post_timing{1}{4}; int n_load_on = post_timing{1}{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanFSwitchNoRef_commanding(band,reffreq,freq_throw,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_per_on,n_load_on,groupnumber,startobs,telescopetimes,loadlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SingleChop_deadtimes("fs",band,reffreq,hr1,hr2,wb1,wb2,data_time,n_per_on); double tscan = 2.0 * (tact{1} + tact{2}); double tdead = 2.0 * tact{2}; // // Call noise computer {double,double,double,double,double} noisevalues = SScanChopNoRef_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,n_per_on * imax(n_load_on,1),true,tscan,tdead); // Evaluate performance SScanChopNoRef_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_per_on * imax(n_load_on,1),groupnumber * n_freq_point,true,tscan,tdead); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } {string,double,double}[] procedure HifiSScanModeFastDBSSequencerInit { string modeName = "freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time / 2); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of DBS modes // Get the drift parameters to compute the drift noise // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double} phaselengths = DBSPhaseLengths(band,reffreq,effResolution,continuumDetection,narrowReference); // Compute derived quantities // Top down approach here int main_phase = iceil(phaselengths{0}); // Arbitrary selection of data_time int data_time_guess = 20; // remaining part for n_switch int n_switch_on_guess = main_phase / (n_freq_point_guess * data_time_guess) + 1; data_time_guess = main_phase / (n_freq_point_guess * n_switch_on_guess); // Check with data rate {int,double[]} dataparms = DataTaking(backendreadoutparms,8); int datalimit = 2 * dataparms{0}; if(data_time_guess < datalimit) { data_time_guess = datalimit; n_switch_on_guess = 1; } int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Chop phase length double phase_min = min(max(phaselengths{1},0.15),1.5); int n_int_on_guess = ifloor(double(data_time_guess) / (2.0 * phase_min)); int n_int_on_range = -n_int_on_guess / 2; if(n_int_on_range == 0) { n_int_on_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } //////////////////////////////////// // DBS raster observing mode // // Combination of four modules implementing the new structure // // Return time and noise levels {int,double,double,double,double,double} obs HifiMappingProcDBSRaster { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Mapping-DBS-Raster",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(nlines,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { DBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////////// // Procedure to calculate the pre timing // {int,int,int,int,int,int,int,int,int,bool,int,int,int} procedure DBS_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_chop = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int inttime = 2 * n_chop * data_time; int readouttime = data_time; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // For double phases I can use the added jitterdead in both phases for load int halfloadlength = (loadlength - jitterdead + 1) / 2; // Compare load interval and nodding interval // This determines the order of the loops int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int n_load = inttime / load_spacing; if(load_spacing > 2 * inttime) { int n_seq = n_chop; bool end_load = false; int pointing = inttime + jitterdead; int shiftlength = 0; } else { n_seq = n_chop / (n_load + 1); if(n_seq < 1) { SError("Chop phase length too long relative to load period."); } end_load = true; inttime = 2 * n_seq * (n_load + 1) * data_time; pointing = inttime + halfloadlength + n_load * loadlength + jitterdead; shiftlength = halfloadlength; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // Compute the overall cycle length // First estimate of the load interval int n_loadinterval = imax(load_interval / (2 * pointing),1); // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {inttime,pointing,readouttime,loadlength,jitterdead,load_spacing,n_load,n_loadinterval,n_seq,end_load,shiftlength,initlength,dangling}; } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for the mode // int procedure Overhead_timing { {double,double} onposition = {0.0,0.0}; // Coordinates of the source {double,double} offposition = {0.2,0.2}; // Coordinates of the OFF position string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int clustered = 0; // whether observation is part of spatial/frequency cluster int data_time = 4 in [0,5]; // data dump interval limited by the data rates }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Interpret data_time=0 as fast-chop if(data_time == 0) { int load_datatime = GetStdLoadReadout(band,lo_freq); CheckDataTaking(backendreadoutparms,load_datatime); } else { load_datatime = data_time; CheckDataTaking(backendreadoutparms,data_time); } // Compute parameters for the instrument timing int pointing = load_datatime; // Resulting integer integration time // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms)); // Duration of initial set up if(clustered == 1) { int initlength = 0; } else { initlength = duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); } initlength = initlength + loadlength; return initlength; } ///////////////////////////////////////////////////////////////// // Auxiliary routine to restrict data_time to match the pointing // requirements condition: tpos >=10s {int,int} procedure MatchMinPointing { int data_time_guess = 4; // initial guess for data_time int data_time_range = 1; // initial guess for range int n_switch = 1; // Number of switches with data_time }{ // pointing requirements condition: >=10s // one second is always added for command jitter if(n_switch * data_time_guess < 9) { data_time_guess = 8 / n_switch + 1; data_time_range = 1; } return {data_time_guess,data_time_range}; } //////////////////////////////////// // Position switch observing mode // // Combination of four modules implementing the new structure // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiPointProcPositionSwitch { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,5]; // data dump interval limited by the data rates int n_int_on = 3 in [2,1800]; // number of data dumps for integration per phase int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-PositionSwitch",{data_time,0,n_int_on,0,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing = PositionSwitch_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},double,double} post_timing = PositionSwitch_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},true); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{4}; int n_loadinterval = post_timing{1}{7}; bool final_load = post_timing{1}{12}; double tscan = post_timing{2}; double tdead = post_timing{3}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { PositionSwitch_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,startobs,telescopetimes,n_loadinterval,loadlength,final_load); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument double tdead_tot = PositionSwitch_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = PositionSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,n_cycles,tscan,tdead_tot); // Evaluate performance PositionSwitch_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,tscan,tdead_tot); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ////////////////////////////////////////////////////////////////////// // Procedure to display performance parameters of the observing mode procedure DBS_performance { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {double,double,double,double,double} noisevalues = {1.0,1.0,1.0,1.0,0.0}; // Noise values from noisecomputer int totaltime = 200; // Total observing time int n_cycles = 1; // Number of nodding cycles int n_chop = 1; // number of chop cycles double tscan = 60.0; // Total average duration of one scan {double,double,double} tact = {10.0,4.9,0.05}; // Field of actual dead and integration times }{ double inttimeperphase = tact{1}; // Actual integration time in ON phase // Get performance of ideal instrument for comparison {int,double,double,double,double,double} idealvalues = IdealInstrument(band,lo_freq,eff_resolution,totaltime); double idealnoise = idealvalues{1} * idealvalues{1}; double obsnoise = noisevalues{0} * noisevalues{0}; double efficiency = idealnoise / obsnoise; // Compute the actual integration time double posinttime = double(n_cycles * 2 * n_chop) * inttimeperphase; int instrumenttime = iceil(double(n_cycles) * tscan); // Check total integration time double timeefficiency = 2.0 * posinttime / double(totaltime); // Noise contribution double relnoise = noisevalues{4} / (1.0 + noisevalues{4}); // General messages PerformanceMessages(band,lo_freq,totaltime,posinttime,posinttime,timeefficiency,efficiency,relnoise,false); } //////////////////////////////////// // Routine to provide initial guesses for sequence parameters // Frequency switch observing mode // {string,double,double}[] procedure HifiPointProcFSwitchNoRefSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half nu1-nu2-nu2-nu1 cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // inherit from load-chop mode {string,double,double}[] retvalues = HifiPointProcLoadChopNoRefSequencerInit(naifid,ra,dec,band,lo_freq,effResolution,oneGHzReference,hrs1,hrs2,wbs1,wbs2,data_time,n_cycles,load_interval,docommands); return retvalues; } //TM to control heater values of LOU, block block HL_heater_block_aot HIFI 6615 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band. string context = "nominal" in ["nominal","stby"]; //whether heater applies to stby or nominal context }{ double[] cresult = CalibrationReader("name_loheater",["heater_nominal","heater_stby"],band,0.0); double hifi_HL_heater = cresult[0]; if(context == "stby") { hifi_HL_heater = cresult[1]; } Hifi_HIFI_HL_heater($BBID,hifi_HL_heater); } // Procedure to get the general parameters for the telescope command // for all engineering observations {int,int} procedure Eng_pre_timing { }{ // Init length int initlength = duration(HIFIInitObs()); int hklength = duration(HIFISetHK("fast",true)); initlength = initlength + hklength; // Final length int closelength = duration(HIFICloseObs()); closelength = closelength + hklength; // telescope parameters - none needed any more // return everything return {initlength,closelength}; } ///////////////////////////////////////////////////////////////// // Routine for spectral scans // // Get the length of the possible frequency steps without recalibration double procedure GetFNoCalibLength { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency }{ double[] nocaliblen = CalibrationReader("fscangroup",["step_nocalib"],band,lo_freq); return nocaliblen[0]; } {int,double,double,double,double,double} obs HifiMappingModeDBSRaster { string modeName = "raster"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Mapping-DBS-Raster",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval}); // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,int} pre_timing = DBSRaster_pre_timing(nlines,npoints,band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_switch_on,n_pointsperscan,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; // Check for NoddingInRaster or NoddingOfRaster int scansize = pre_timing{10}; if(scansize > 1) { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,double,double,int,int,int,int,int} tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_of_raster_pointing(false,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { {int,int,int,string,int,double,double,bool,double,double,double,int,int,double,double,int,int,int,double,double,int,int,int,double,double,int,int,int,int} tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",pre_timing,n_cycles); telescopetimes = nodding_raster_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,int},bool,double,double} post_timing = DBSRaster_post_timing(pre_timing,telescopetimes,nlines,npoints,n_switch_on,n_cycles,load_interval,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command if(scansize > 1) { tmpar = DBSMultiRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_of_raster_pointing(true,tmpar{0},tmpar{1},tmpar{2},tmpar{3},tmpar{4},tmpar{5},tmpar{6},tmpar{7},tmpar{8},tmpar{9},tmpar{10},tmpar{11},tmpar{12},tmpar{13},tmpar{14},tmpar{15},tmpar{16},tmpar{17},tmpar{18},tmpar{19},tmpar{20},tmpar{21},tmpar{22},tmpar{23}); } else { tpar = DBSRaster_telescope(naifid,onPosition,lineDistance,stepsize,nlines,npoints,band,lo_freq,"",post_timing{1},n_cycles); telescopetimes = nodding_raster_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},tpar{19},tpar{20},tpar{21},tpar{22},tpar{23},tpar{24},tpar{25},tpar{26},tpar{27},tpar{28}); } // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; int initlength = post_timing{1}{11}; int dangling = post_timing{1}{12}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { DBSRaster_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_cycles,scansize,n_loadinterval,n_load,final_load,startobs,telescopetimes,loadlength,false); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the noise // // First get additional dead times from instrument {double,double,double} tact = DBSRaster_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_seq,n_load,scansize,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBSRaster_performance(band,lo_freq,effResolution,noisevalues,timeTaken,nlines,npoints,n_cycles,n_seq * imax(n_load,1),tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } ////////////////////////////////////////////////////////////////////////// // Procedure to compute detailed timing of OTF observing mode {int,int,int,int,int,int,int,int} procedure OTFFSwitch_pre_timing { int nlines_tot = 1; // Number of rows in the map int npoints = 10; // Number of data dumps per row string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_switch_off = 3 in [1,3600]; // Number of data dumps for the OFF integration time int n_linesperscan = 1 in [1,32]; // Number of lines between two OFFs int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq + min(freq_throw,0.0),lo_freq + max(freq_throw,0.0)); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); CheckFswOutOfBand(band,lo_freq,freq_throw,backendreadoutparms); // Is the map size an integer multiple of the scan size? CheckReasonableLineNumber(nlines_tot,true); if(nlines_tot == 1) { int n_scans = 1; } else { if(nlines_tot % n_linesperscan != 0) { SError("Map size is no integer multiple of the scan size."); } n_scans = nlines_tot / n_linesperscan; } // Compute parameters for the instrument timing int n_pp = 2 * npoints * n_switch_on; // compute load integration time int loadlength = duration(DoubleLoadMeasurement(band,lo_freq,freq_throw,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compute parameters for the pointing command int jitterdead = GetMaxTimeJitter(band,lo_freq); int off_inttime = 2 * data_time_off * n_switch_off; // OFF integration time int off_pointing = off_inttime + jitterdead; // increase by commanding jitter // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFIFsw(band,lo_freq,freq_throw,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,true); } initlength = initlength + loadlength; // First estimate of the load interval int scan_time = n_linesperscan * n_pp * data_time + off_pointing; if(scan_time > load_interval) { IError("Scan duration too long for required load period. " + "Reduce the map size or increase the step size."); } int n_loadinterval = imax(load_interval / scan_time,1); n_loadinterval = imin(n_loadinterval,32); // Make sure that load slews occur at the same position in each coverage n_loadinterval = IMultiple(n_loadinterval,n_scans); // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed in the observing mode modules return {n_pp,n_scans,off_inttime,off_pointing,loadlength,n_loadinterval,initlength,dangling}; } // SCR-1243: 14.4 and 14.42 are prohibited LO - shift it to 14.38 and 14.44 GHz double procedure Check_HRS_prohibited_LO_proc_fm { double flo = 15.0; // Input HRS internal LO freq. in GHz }{ double checked_flo = flo; if(checked_flo == 14.4) { checked_flo = flo - 0.02; } if(checked_flo == 14.42) { checked_flo = flo + 0.02; } return checked_flo; } ///////////////////////////////////////////////////////////////// // Procedure to compute total dead times for the mode // {double,double,double} procedure DBS_deadtimes { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // data dump interval int n_chop = 3; // number of chop cycles in one integration int n_load = 0; // number of integrations in one pointing phase -1 double tdead = 10.0; // Dead time from telescope }{ ////////////////////////////////////////////////////////////////////// // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Compute parameters for the instrument timing {double,double} tinst = GetInstDeadSlowChop(data_time,2 * n_chop,"chop",band,lo_freq,backendreadoutparms); // dead time double tdeadint = double(data_time * 2 * n_chop) - tinst{0}; // subtract dead times in switches // keep dead times between A-A and B-B in total dead time tdeadint = tdeadint - double(n_chop) * tinst{1}; // Total dead time per cycle double tdead_tot = tdead + double(2 * (n_load + 1)) * tdeadint; // Integration time double tphaseint = tinst{0} / double(2 * n_chop); return {tdead_tot,tphaseint,tinst{1}}; } {string,double,double}[] procedure HifiPointModeLoadChopNoRefSequencerInit { string modeName = "load"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_cycles = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int data_time_guess = imin(imax(iceil(0.3 * allan_time_lores),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Contruct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)}]; return retvalues; } ///////////////////////////////////////////////////////////////// // Calibration file reader for spectral scans. This is a variant of the // CalibrationReader including the dependence on the redundancy instead // of the LO frequency // double[] procedure SpectralScanReader { string topicname = "fscanedge"; // Name of entry in master file string[] objectnames = ["edgelength"]; // Names of calibration objects to be read string band = "4a"; // HIFI band int redundancy = 4; // Redundancy factor }{ // first step: read master file string calibfile = slookup("spectralscan_masterfile",topicname,"filename"); int dep = ilookup("spectralscan_masterfile",topicname,"dependence"); string sredun = "" + redundancy; int readnum = length(objectnames); double[] retvalues = []; if(dep == 0) { // Quantity is constant // Read from single file by name for(int i = 1 .. readnum) { retvalues[i - 1] = dlookup(calibfile,objectnames[i - 1],"value"); } } else { if(dep == 1) { // Quantity is only redundancy dependent // directly read from file for(int k = 1 .. readnum) { retvalues[k - 1] = dlookup(calibfile,sredun,objectnames[k - 1]); } } else { // Quantity is band and redundancy dependent // second step step: band look up, get name of responsible data file string actualfile = slookup(calibfile,band,"filename"); // Now lookup data according to redundancy for(int j = 1 .. readnum) { retvalues[j - 1] = dlookup(actualfile,sredun,objectnames[j - 1]); } } } return retvalues; } //////////////////////////////////// // Routine to provide initial guesses for sequence parameters // Load chop observing mode // {string,double,double}[] procedure HifiPointProcLoadChopSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half load-sky-sky-load cycles on ON int n_switch_off = 2 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section {double,double,double,double} phaselengths = LoadChopPhaseLengths(band,lo_freq,effResolution,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_switch_on_guess = imax(iceil(phaselengths{0} / (2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; new_data_time = MatchMinPointing(data_time_off_guess,data_time_off_range,2 * n_switch_off_guess); data_time_off_guess = new_data_time{0}; data_time_off_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)}]; return retvalues; } // Radiometric noise from a symmetric two-phase observation // This is still to be scaled by a factor 1.0/(B_fluct*T_Allan) double procedure TwoPhaseRadioNoise { double x = 0.1; // value for integration time relative to Allan time }{ double y = AsymmetricRadioNoise(x,x,1.0); return y; } ////////////////////////////////////////////////////////////////// // Procedure to compute detailed pre timing for the version of the // load chop mode without baseline measurement // {int,int,int,int,int,int,bool,int,int} procedure LoadChopNoRef_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_chop_on = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int on_inttime = 2 * n_chop_on * data_time; // compute load integration time int loadlength = duration(LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compare load interval with duration of the observation int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int n_load_on = on_inttime / load_spacing; // This determines the order of the loops if(load_spacing > 2 * on_inttime) { int n_per_on = n_chop_on; bool end_load_on = false; int on_pointing = on_inttime + jitterdead; } else { n_per_on = n_chop_on / (n_load_on + 1); if(n_per_on < 1) { SError("Chop phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * (n_load_on + 1) * data_time; on_pointing = on_inttime + n_load_on * loadlength + jitterdead; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {on_inttime,on_pointing,loadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling}; } ////////////////////////////////////////////////////////////////// // Procedure to compute detailed pre timing for the version of the // load chop mode without baseline measurement // {int,int,int,int,int,int,bool,int,int} procedure LoadChopNoRef_FCal_pre_timing { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rates int n_chop_on = 2 in [1,3600]; // number of half load-sky-sky-load cycles on ON int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // First check validity of frequencies CheckLOFrequencies(band,lo_freq,lo_freq); // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // First perform consistency checks // Check chunk size given by the data rates CheckDataTaking(backendreadoutparms,data_time); int jitterdead = GetMaxTimeJitter(band,lo_freq); // Compute parameters for the instrument timing int on_inttime = 2 * n_chop_on * data_time; // compute load integration time int loadlength = duration(LoadMeasurement_FCal(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); loadlength = loadlength + readoutdead; // Compare load interval with duration of the observation int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); int n_load_on = on_inttime / load_spacing; // This determines the order of the loops if(load_spacing > 2 * on_inttime) { int n_per_on = n_chop_on; bool end_load_on = false; int on_pointing = on_inttime + jitterdead; } else { n_per_on = n_chop_on / (n_load_on + 1); if(n_per_on < 1) { SError("Chop phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * (n_load_on + 1) * data_time; on_pointing = on_inttime + n_load_on * loadlength + jitterdead; } // Duration of initial set up // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,lo_freq,false); } initlength = initlength + loadlength; // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {on_inttime,on_pointing,loadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling}; } ///////////////////////////////////////////////////////////////// // Fast chop dual beam switch observing mode - special version for Jupiter // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiPointProcJupiterFastDBS { /* Setup parameters */ int naifid = 0; // Tracing object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 10 in [4,80]; // data dump interval int n_int_on = 20 in [1,640]; // number chop cycles to integrate in ICU before transfer int n_switch_on = 1 in [1,1800]; // number of data transfer cycles per pointing int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-Jupiter-FastChop-DBS",{data_time,0,n_int_on,n_switch_on,0,0,0,0,n_cycles,load_interval}); // Call first part of the timing computer // Two changes relative to the normal DBS // 1) The longer load duration is enforced by zero resolution {double,double} loadResolution = {0.0,effResolution{1}}; // 2) I assume that the tuning duration does not depend on the tuning level // so that the normal pre_timing can be reused. {int,int,int,int,int,int,int,int,int,bool,int,int,int} pre_timing = FastDBS_pre_timing(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_switch_on,n_cycles,load_interval,docommands); ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",pre_timing,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},bool,double,double} post_timing = DBS_post_timing(pre_timing,telescopetimes,n_cycles); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,lo_freq,"",post_timing{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following int loadlength = post_timing{1}{3}; int n_load = post_timing{1}{6}; int n_loadinterval = post_timing{1}{7}; int n_seq = post_timing{1}{8}; bool end_load = post_timing{1}{9}; int shiftlength = post_timing{1}{10}; bool final_load = post_timing{2}; double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { JupiterFastDBS_commanding(band,lo_freq,loadResolution,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,n_loadinterval,end_load,final_load,startobs,telescopetimes,loadlength,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = FastDBS_deadtimes(band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,n_int_on,n_seq,n_load,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = DBS_noisecomputer(band,lo_freq,effResolution,continuumDetection,oneGHzReference,n_cycles,tscan,tact); // Evaluate performance DBS_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_seq * n_int_on * (n_load + 1),tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Continuous HIFI integration with given backend settings at line scan block HIFIContOtfIntegration HIFI 6023 { int n_int = 1; // Integration time counter int data_time = 4; // Integration time between two data readouts double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_tp_proc_aot(n_int,data_time,rates); } // Fast chop integration OFF-ON-OFF-ON... with telescope at ON position block HIFIFastChopOnIntegration HIFI 6042 { int data_time = 4; // Integration time between two data readouts int n_cycle = 1; // readout cycle number string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz int[] parms = [1,0]; // Parameters for chop cycles double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_fast_chop_proc_aot(data_time,n_cycle,band,lo_freq,["chop_M3left","chop_M3right"],parms,rates); } // Total noise from an OTF line for the special case of a // multiple scan of the same line // Normalized to mapping without overhead // double procedure OtfRepeatedNoise { double num_scans = 2.0; // number of scans of the same line double n = 10.0; // number of points in one scan double[] parameters = [0.02,0.4,0.05,0.667,2.5]; // Parameters: integration time, delay, slew from OFF relative to Allan time, ratio of t_off time to sqrt(n)*t_on, drift exponent }{ // Assign parameters double x = parameters[0]; double d = parameters[1]; double doff = parameters[2]; double qval = parameters[3]; double alpha = parameters[4]; // Make corrections for different calibration double qcorr = qval * sqrt(num_scans); {double,double} noisevalues = OtfNoiseValues(num_scans * n,[x,d,doff,qcorr,alpha]); // The radiometric noise here is only accurate for nscans=1,2. // For other lengths we make a small error. double yn = noisevalues{0}; yn = yn / num_scans; // The drift noise might also be reduced somewhat due to adding up // different scans. The effect is basically unknown and ignored here. double yd = noisevalues{1}; double y = yn + yd; return y; } ///////////////////////////////////////////////////////////////// // Spectral scan in DBS observing modes // // Combination of four modules implementing the new structure // // Implemented as procedure returning time and noise levels for HSPOT {int,double,double,double,double,double} obs HifiSScanProcDBS { /* Setup parameters */ int naifid = 0; // Tracing object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4 in [1,12]; // Frequency scan redundancy {double,double} effResolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool wbs1Used = true; // whether WBS1 is used bool wbs2Used = true; // whether WBS2 is used /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-SScan-DBS",{data_time,0,0,n_switch_on,0,0,0,n_freq_point,n_cycles,load_interval}); // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; ////////////////////////////////////////////////////////////////////// // Call first part of the timing computer {{int,int,int,int,int,int,int,int,int,bool,int,int,int},{int,double,double[],int[][],bool,double[],int,bool}} pre_timing = SScanDBS_pre_timing(band,lo_freq,lo_freq_up,redundancy,effResolution,hr1,hr2,wb1,wb2,data_time,n_switch_on,n_freq_point,n_cycles,load_interval,docommands); // frequency parameters int groupnumber = pre_timing{1}{0}; double reffreq = pre_timing{1}{1}; double[] freqgrid = pre_timing{1}{2}; int[][] grouporder = pre_timing{1}{3}; bool retuning = pre_timing{1}{4}; double[] targetlevels = pre_timing{1}{5}; int nfreq_if = pre_timing{1}{6}; bool dsb = pre_timing{1}{7}; int n_total = groupnumber * n_cycles; ////////////////////////////////////////////////////////////////////// // Prepare telescope command {double,double} onPosition = {ra,dec}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",pre_timing{0},n_total); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); ////////////////////////////////////////////////////////////////////// // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,bool,int,int,int},double,double,double} post_timing = SScanDBS_post_timing(pre_timing{0},telescopetimes,n_freq_point,groupnumber,n_cycles,false); ////////////////////////////////////////////////////////////////////// // Now the observation starts for the telescope // Prepare telescope command tpar = DBS_telescope(naifid,onPosition,band,reffreq,"",post_timing{1},n_total); // Call telescope command telescopetimes = nodding_pointing(true,tpar{0},tpar{1},tpar{2},tpar{3},tpar{4},tpar{5},tpar{6},tpar{7},tpar{8},tpar{9},tpar{10},tpar{11},tpar{12},tpar{13},tpar{14},tpar{15},tpar{16},tpar{17},tpar{18},false); // Consistency check int totaltime = post_timing{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following // normal pre_timing values int n_loadinterval = post_timing{1}{7}; int n_bchop = post_timing{1}{8}; int shiftlength = post_timing{1}{10}; int initlength = post_timing{1}{11}; double avnumchop = post_timing{2}; // efficiency parameters double tscan = post_timing{3}; double tdead = post_timing{4}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands /////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { SScanDBS_commanding(band,reffreq,effResolution,hr1,hr2,wb1,wb2,n_freq_point,grouporder,freqgrid,retuning,targetlevels,data_time,n_cycles,n_total,n_bchop,n_switch_on,n_loadinterval,startobs,telescopetimes,shiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double} tact = SScanDBS_deadtimes(band,reffreq,hr1,hr2,wb1,wb2,n_freq_point,data_time,n_bchop,n_switch_on,n_cycles,avnumchop,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = SScanDBS_noisecomputer(band,reffreq,nfreq_if,dsb,effResolution,continuumDetection,n_cycles,tscan,tact); // Evaluate performance SScanDBS_performance(band,reffreq,nfreq_if,dsb,effResolution,noisevalues,timeTaken,n_total,groupnumber * n_freq_point,avnumchop,tscan,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // Load chop observing mode // // The implementation now assumes that the corresponding Herschel // pseudo-pointing mode will be available // {int,double,double,double,double,double} obs HifiPointProcLoadChop { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source double raoff = 0.0; // RA coordinate of the OFF position double decoff = 0.0; // DEC coordinate of the OFF position bool refSelected = true; // Dummy parameter required by HSPOT string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[36,2012],[36,2012],[36,2012],[36,2012]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half load-sky-sky-load cycles on ON int n_switch_off = 2 in [1,900]; // number of half load-sky-sky-load cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = true; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode OpenMessages("Hifi-Point-LoadChop",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,0,n_cycles,load_interval}); // position switch // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing_ps = LoadChop_pre_timing(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,pre_timing_ps,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},int,bool,double,double} post_timing_ps = DoubleChop_post_timing(pre_timing_ps,telescopetimes,n_cycles); // Now the actual observation starts // Prepare telescope command tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,post_timing_ps{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Consistency check int totaltime = post_timing_ps{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// int on_inttime = post_timing_ps{1}{0}; int off_inttime = post_timing_ps{1}{1}; int on_pointing = post_timing_ps{1}{2}; int off_pointing = post_timing_ps{1}{3}; int loadlength = post_timing_ps{1}{4}; int n_loadinterval = post_timing_ps{1}{7}; int n_per_on = post_timing_ps{1}{8}; int n_per_off = post_timing_ps{1}{9}; int n_load_on = post_timing_ps{1}{10}; int n_load_off = post_timing_ps{1}{11}; bool end_load_on = post_timing_ps{1}{12}; bool end_load_off = post_timing_ps{1}{13}; int initshiftlength = post_timing_ps{2}; bool final_load = post_timing_ps{3}; double tscan = post_timing_ps{4}; double tdead = post_timing_ps{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { LoadChop_commanding(band,lo_freq,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_loadinterval,n_load_on,n_load_off,end_load_on,end_load_off,final_load,startobs,telescopetimes,loadlength,initshiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = DoubleChop_deadtimes("lchop",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_load_on,n_load_off,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = LoadChop_noisecomputer(band,lo_freq,effResolution,oneGHzReference,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance DoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_per_on * (n_load_on + 1),n_per_off * (n_load_off + 1),false,tscan,on_pointing,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } //////////////////////////////////// // Function to estimate the initial overhead used within CUS // // From the current implementation of the pointing modes it seems // that the initail slew is never used as part of the total time // This needs confirmation for cases with tuning+load > required slew int procedure InitialCusOverhead { /* Setup parameters */ {double,double} onPosition = {0.0,0.0}; // Coordinates of the source {double,double} refPosition = {0.2,0.2}; // Coordinates of the OFF position string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int clustered = 0; // whether observation is part of spatial/frequency cluster int data_time = 4; // data dump interval limited by the data rates; a value of 0 will be interpreted as fast-chop mode where we use a default rate }{ ////////////////////////////////////////////////////////////////////// // Call timing computer // // With the new pointing modes the initial overhead is always // excluded from the total observing time now // // int timing=Overhead_timing( // onPosition,refPosition,band,lo_freq,effResolution, // hrs1,hrs2,wbs1,wbs2,clustered,data_time); int timing = 0; return timing; } // Tune for frequency switch procedure TuneHIFIFsw { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz double freq_throw = -40.0; // throw of frequency switch in MHz {bool,int,double[],bool[]} hrs1parms = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets,subbands used} {bool,int,double[],bool[]} hrs2parms = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets,subbands used} bool wbs1parms = true; // WBS1 parameter =used bool wbs2parms = true; // WBS2 parameter =used string level = "normal"; // Name of target level }{ // Check for allowed configuration double maxstep = GetMaxFreqThrow(band,lo_freq); if(abs(freq_throw) > maxstep) { int show_lo = ifloor(lo_freq / 1000.0); IError("Frequency throw too large. Maximum throw allowed at " + show_lo + "GHz: " + maxstep + "MHz."); } // Switch to high HK rate HIFISetHK("fast",true); ConfigureFPU(band,lo_freq + freq_throw / 2.0,true); ConfigureBackend(band,lo_freq + freq_throw / 2.0,hrs1parms,hrs2parms); HIFITuneFsw(band,lo_freq,lo_freq + freq_throw,hrs1parms{0},hrs2parms{0},wbs1parms,wbs2parms,level); // Switch to standard HK rate HIFISetHK("normal",true); } ////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the observing mode {double,double,double,double,double} procedure LoadChop_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int on_inttime = 16; // Integration time per ON phase int off_inttime = 16; // Integration time per OFF phase int n_cycles = 1; // Number of half OFF-ON-ON-OFF calibration cycles double tscan = 60.0; // Total average duration of one scan {double,double,double,double,double} tact = {10.0,4.9,4.9,0.05,0.05}; // Field of actual dead and integration times }{ double tdead = tact{0}; // Average total dead time in one scan double inttimeperonphase = tact{1}; // Actual integration time in ON phase double inttimeperoffphase = tact{2}; // Actual integration time in OFF phase double deadtimeperonphase = tact{3}; // Dead time per switch phase on ON // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Differential Allan variance allanparms = InterpolateSpecLChopAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double dalpha = allanparms[1]; binningexp = 1.0 / allanparms[2]; double dallan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double dallan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // resolution of OFF phase double sw_resolution = GetLoadChopSWResolution(band,lo_freq); double sw_resolution_lores = max(eff_resolution{1},sw_resolution); double sw_resolution_hires = max(eff_resolution{0},sw_resolution); // Compute the relative noise for the detailed timing double on_int = double(on_inttime); double off_int = double(off_inttime); // The dead time per switch might deviate between ON and OFF - ignored double deadtimeperswitch = deadtimeperonphase; // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = DoubleDifferenceNoise(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); double systemnoise_hires = DoubleDifferenceNoise(inttimeperonphase / allan_time_hires,[inttimeperoffphase / inttimeperonphase,sw_resolution_hires / eff_resolution{0},on_int / allan_time_hires,off_int / allan_time_hires,deadtimeperswitch / allan_time_hires,tdead / allan_time_hires,alpha,dallan_time_hires / allan_time_hires,dalpha]); double noiseratio = DoubleDifferenceNoiseRatio(inttimeperonphase / allan_time_lores,[inttimeperoffphase / inttimeperonphase,sw_resolution_lores / eff_resolution{1},on_int / allan_time_lores,off_int / allan_time_lores,deadtimeperswitch / allan_time_lores,tdead / allan_time_lores,alpha,dallan_time_lores / allan_time_lores,dalpha]); // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 1000000.0 * double(n_cycles) * tscan)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 1000000.0 * double(n_cycles) * tscan)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiseratio}; } //////////////////////////////////// // DBS raster observing mode // // Return time and noise levels {string,double,double}[] procedure HifiMappingProcDBSRasterSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,100]; // Number of rows in the map double stepsize = 0.0050 in [5.5556E-4,0.13333]; // Distance between subsequent points in the raster line int npoints = 10 in [2,100]; // Number of points per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool continuumDetection = false; // Whether timing is for total-power level bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_switch_on = 2 in [1,900]; // number of half sky1-sky0-sky0-sky1 cycles per pointing int n_pointsperscan = 1 in [1,1024]; // Number of points measured before moving to the second pointing phase int n_cycles = 1 in [1,32]; // Number of half OFF-ON-ON-OFF pointing cycles int load_interval = 1800 in [10,7200]; // load period = f(band,lo_freq,effResolution{1}) bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // Get the drift parameters to compute the drift noise {double,double} phaselengths = DBSPhaseLengths(band,lo_freq,effResolution,continuumDetection,oneGHzReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // Combine points for n_switch=1 int main_phase = iceil(phaselengths{0}); int n_pointsperscan_guess = imin(imax(main_phase / (2 * data_time_guess),1),npoints * nlines); int n_pointsperscan_range = 1 - n_pointsperscan_guess; if(n_pointsperscan_range == 0) { n_pointsperscan_range = 1; } // remaining part for n_switch int n_switch_on_guess = main_phase / (n_pointsperscan_guess * 2 * data_time_guess) + 1; int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,2 * n_switch_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_pointsperscan",double(n_pointsperscan_guess),double(n_pointsperscan_range)}]; return retvalues; } /////////////////////////////////////////////////////////////////// // Procedure to compute detailed post timing for the version of the // load chop mode without baseline measurement // {int,{int,int,int,int,int,int,bool,int,int},double,double} procedure SingleChopNoRef_post_timing { {int,int,int,int,int,int,bool,int,int} pre_timing = {16,16,21,1800,2,0,false,50,0}; // pre_timing parameter list int[] telescopetimes = [300,180,0]; }{ // Get all values from the pre_timing section int on_inttime = pre_timing{0}; int on_pointing = pre_timing{1}; int loadlength = pre_timing{2}; int load_spacing = pre_timing{3}; int n_per_on = pre_timing{4}; int n_load_on = pre_timing{5}; bool end_load_on = pre_timing{6}; int initlength = pre_timing{7}; int dangling = pre_timing{8}; // Get all values from the telescope section int tend = telescopetimes[2]; // Final deceleration time // No further computations needed int looplength = on_pointing; double tscan = double(on_inttime) / double(n_per_on * (n_load_on + 1)); // No telescope dead time in fine pointing double tdead = 0.0; // dangling load time if(end_load_on) { dangling = loadlength; } int closelength = duration(HIFICloseObs()); dangling = imax(dangling + closelength - tend,0); // Compute total duration // The initial time is no longer contained in the total time // int totaltime=imax(initlength,telinit); int totaltime = looplength + dangling + tend; // show gyro-propagation messages // no gyro-propagation for fine_pointing GCPMessages(0,on_pointing,tend); // Return all the times needed in the telescope and instrument modules return {totaltime,{on_inttime,on_pointing,loadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling},tscan,tdead}; } {string,double,double}[] procedure HifiPointModePositionSwitchSequencerInit { string modeName = "pos"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,5]; // data dump interval limited by the data rates int n_int_on = 3 in [2,1800]; // number of data dumps for integration per phase int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int int_time_guess = imax(iceil(0.3 * allan_time_lores),datalimit); int data_time_guess = imin(5,int_time_guess); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } int n_int_on_guess = imax(int_time_guess / data_time_guess,2); int n_int_on_range = 2 - n_int_on_guess; if(n_int_on_range == 0) { n_int_on_range = 1; } // Add pointing requirements condition: >=10s {int,int} new_data_time = MatchMinPointing(data_time_guess,data_time_range,n_int_on_guess); data_time_guess = new_data_time{0}; data_time_range = new_data_time{1}; // Contruct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_int_on",double(n_int_on_guess),double(n_int_on_range)}]; return retvalues; } // Automatic magnet tuning, block // Also assumes backends are ready // This is to be used in cold context block Magnet_tuning_block_aot HIFI 6609 { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b"]; // HIFI band double lo_freq = 978.2; //LO frequency string backend_code = "HRS" in ["WBS","HRS"]; //The backend to be used for tuning }{ //Set mixer bias to special bias for tuning {double,string}[] result = ConfigurationReader("name_confilmix",["bias4magn_h","bias4magn_v","norm_bias_h","norm_bias_v"],band,lo_freq); //For bands 1,2 and 5, we must substract 0.09mV to this value double bias4magnh = result[0]{0}; double bias4magnv = result[1]{0}; if(band == "1a" || band == "1b" || band == "2a" || band == "2b" || band == "5a" || band == "5b") { bias4magnh = bias4magnh - 0.09; bias4magnv = bias4magnv - 0.09; } Mixerbias(bias4magnh,bias4magnv); double normal_bias_h = result[2]{0}; double normal_bias_v = result[3]{0}; // //First set magnets to maximum because of hysteresis result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,lo_freq); double magnetcurrentmax_H = result[0]{0}; double magnetcurrentmax_V = result[1]{0}; Set_Magnet_current_proc_fm(magnetcurrentmax_H,magnetcurrentmax_V); //For band5, wait another 5 sec here if(band == "5a" || band == "5b") { delay(5); } // //Fetch magnet tuning parameters //Middle of the scan result = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v"],band,lo_freq); double h_mx_mg0 = result[0]{0}; double v_mx_mg0 = result[1]{0}; // result = ConfigurationReader("name_configmagtune",["nMagnet","stepT","mx_mg_span"],band,lo_freq); // //Tuning strategy: scan nMagnet points over -span/2 to +span/2% of nominal value //at the frequency of interest int nMagnet = iround(result[0]{0}); double stepT = result[1]{0}; double mx_mg_span = result[2]{0}; double scan_range = mx_mg_span * max(h_mx_mg0,v_mx_mg0) / 100.0; double mx_mg_step = -1.0 * scan_range / double(nMagnet); //Starting scan values h_mx_mg0 = h_mx_mg0 - mx_mg_step * double(nMagnet) / 2.0; v_mx_mg0 = v_mx_mg0 - mx_mg_step * double(nMagnet) / 2.0; // //Set magnets to starting value to do backend tuning Set_Magnet_current_proc_fm(h_mx_mg0,v_mx_mg0); // //Tune attenuators of backends before magnet tuning result = ConfigurationReader("name_configwbs",["tune_target_magnet"],band,lo_freq); int tune_target_magnet = iround(result[0]{0}); // //Perform tuning: check which backend shall be used int magtune_delay = 0; if(backend_code == "WBS") { Hifi_HIFI_Tune_WBS($BBID,tune_target_magnet); //Get delay result = ConfigurationReader("name_delays",["wbs_tune_delay"],band,0.0); delay(iround(result[0]{0})); // Hifi_HIFI_Tune_mxmgc_useWBS($BBID,stepT,nMagnet,h_mx_mg0,v_mx_mg0,mx_mg_step); //Compute delay magtune_delay = iceil(1.0 + 0.94 + double(nMagnet) * (stepT + 1.05)); //according to OBS 4.4 } else { Hifi_HIFI_Tune_HRS($BBID); //Get delay result = ConfigurationReader("name_delays",["hrs_tune_delay"],band,0.0); delay(iround(result[0]{0})); // Hifi_HIFI_Tune_mxmgc_useHRS($BBID,stepT,nMagnet,h_mx_mg0,v_mx_mg0,mx_mg_step); magtune_delay = iceil(1.0 + 0.072 + double(nMagnet) * (stepT + 0.132)); //according to OBS 4.4 } // delay(magtune_delay); //debug_print(magtune_delay); //Set mixer bias back to nominal value at frequency of interest Mixerbias(normal_bias_h,normal_bias_v); // } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the observing mode procedure PositionSwitch_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size int n_int = 3; // number of data dumps for integration per chop phase int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope int n_loadinterval = 10; // number of nods before a load measurement int loadlength = 21; // Load duration bool final_load = false; // Need for final load measurement }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int tnodslew = telescopetimes[2]; // slew dead time between points // Consistency checks are performed in the telescope procedure //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] rates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 7) { // OFF Integration HIFIConfigureContIntegration(data_time,n_int,band,lo_freq,backendreadoutparms); HIFIContOffIntegration(data_time,n_int,rates); // Does a nod slew follow? occurs for odd cycle numbers if(state[2] % 2 == 1 && state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } if(state[0] == 3) { // ON integration HIFIConfigureContIntegration(data_time,n_int,band,lo_freq,backendreadoutparms); HIFIContOnIntegration(data_time,n_int,rates); // Does a nod slew follow? occurs for even cycle numbers if(state[2] % 2 == 0 && state[2] % n_loadinterval > 0) { HIFIActiveHK("normal",tnodslew); } } if(state[0] == 9) { // Load nod delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 5) { delay(readoutdead); if(final_load) { LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } HIFICloseObs(); } } } {string,double,double}[] procedure HifiSScanModeFSwitchSequencerInit { string modeName = "fs-freq"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_switch_off = 1 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int n_cycles = 1 in [1,600]; // Number of half OFF-ON-ON-OFF cycles at one frequency int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode // First get the backend configuration {{bool,int,double[],bool[]},{bool,int,double[],bool[]},{bool,int[][]},{bool,int[][]}} backends = SScanBackendSettings(band,redundancy,wbs1Used,wbs2Used,data_time); {bool,int,double[],bool[]} hr1 = backends{0}; {bool,int,double[],bool[]} hr2 = backends{1}; {bool,int[][]} wb1 = backends{2}; {bool,int[][]} wb2 = backends{3}; {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hr1{0},hr1{1},hr1{3}},{hr2{0},hr2{1},hr2{3}},wb1,wb2}; // Get frequency grid characteristic parameters {double,int,double} gfref = GetFReference(band,lo_freq,lo_freq_up); double reffreq = gfref{0}; int stdredun = gfref{1}; double stdstep = gfref{2}; int increment = stdredun / redundancy; // allowed group size double nocaliblen = GetFNoCalibLength(band,reffreq); int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0); int n_freq_point_range = 1 - n_freq_point_guess; if(n_freq_point_range == 0) { n_freq_point_range = 1; } // Now general part of Frequency switch modes {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // spectral scans always use the full bandwidth for reference bool narrowReference = false; {double,double,double,double} phaselengths = FSwitchPhaseLengths(band,lo_freq,effResolution,narrowReference); // Compute derived quantities int data_time_guess = imin(imax(iceil(phaselengths{1}),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // How much time for single ON phase int n_switch_on_guess = imax(iceil(2.0 * phaselengths{0} / ((double(n_freq_point_guess) + sqrt(double(n_freq_point_guess))) * 2.0 * double(data_time_guess))),1); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // OFF phase int data_time_off_guess = imin(imax(iceil(phaselengths{2}),datalimit),20); int data_time_off_range = datalimit - data_time_off_guess; if(data_time_off_range == 0) { data_time_off_range = 1; } int n_switch_off_guess = imax(iceil(double(data_time_guess * n_switch_on_guess) * sqrt(double(n_freq_point_guess)) / (double(data_time_off_guess) * sqrt(phaselengths{3} / effResolution{1}))),1); int n_switch_off_range = 1 - n_switch_off_guess; if(n_switch_off_range == 0) { n_switch_off_range = 1; } // Construct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"data_time_off",double(data_time_off_guess),double(data_time_off_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)},{"n_switch_off",double(n_switch_off_guess),double(n_switch_off_range)},{"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)}]; return retvalues; } {int,double,double,double,double,double} obs HifiPointModeFSwitch { string modeName = "fs"; int goalTime = 180; double goalNoise = 0.1; bool doingTime = true; double ra = 0.0; double dec = 0.0; double raoff = 0.0; double decoff = 0.0; bool refSelected = true; int naifid = 0; string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band string spectrometer = "both"; bool hrsSeparatePol = false; string hrsModeH = "Nominal"; string hrsModeV = "Nominal"; double fe_lof_0 = 978.2; double fe_hrs1_h_0 = 0.0; double fe_hrs2_h_0 = 0.0; double fe_hrs3_h_0 = 0.0; double fe_hrs4_h_0 = 0.0; double fe_hrs1_v_0 = 0.0; double fe_hrs2_v_0 = 0.0; double fe_hrs3_v_0 = 0.0; double fe_hrs4_v_0 = 0.0; double fe_eff_res_min_0 = 1.1; double fe_eff_res_max_0 = 1.1; bool resolutionMhz = true; bool singleWbs = false; int redundancy = 4; bool dbsContinuum = true; bool oneGHzReference = true; double lo_freq1 = 978.2; double lo_freq2 = 979.6; bool fullRange = true; string fsThrow = "small-negative"; double flyX = 0.0; double flyY = 0.0; double flyAngle = 0.0; bool flyNyquistSel = false; double flyCrossStep = 10.0; string crossStepSize = "jitter" in ["jitter","nyquist","10","20","40"]; // HSPOT-only parameters beyond this line. bool dbsFast = true; bool fastChop = true; string frame = "LSR"; string redshiftFrame = "heliocentric"; string redshiftType = "redshift"; double redshift = 0.0; string fe_wbs_line_0 = "-No Lines-"; string fe_wbs_trans_0 = "-No Lines-"; double fe_wbs_freq_0 = -1.0; bool fe_wbs_usb_0 = true; string fe_hrs1_h_line_0 = "-No Lines-"; string fe_hrs1_h_trans_0 = "-No Lines-"; double fe_hrs1_h_freq_0 = -1.0; bool fe_hrs1_h_usb_0 = true; string fe_hrs2_h_line_0 = "-No Lines-"; string fe_hrs2_h_trans_0 = "-No Lines-"; double fe_hrs2_h_freq_0 = -1.0; bool fe_hrs2_h_usb_0 = true; string fe_hrs3_h_line_0 = "-No Lines-"; string fe_hrs3_h_trans_0 = "-No Lines-"; double fe_hrs3_h_freq_0 = -1.0; bool fe_hrs3_h_usb_0 = true; string fe_hrs4_h_line_0 = "-No Lines-"; string fe_hrs4_h_trans_0 = "-No Lines-"; double fe_hrs4_h_freq_0 = -1.0; bool fe_hrs4_h_usb_0 = true; string fe_hrs1_v_line_0 = "-No Lines-"; string fe_hrs1_v_trans_0 = "-No Lines-"; double fe_hrs1_v_freq_0 = -1.0; bool fe_hrs1_v_usb_0 = true; string fe_hrs2_v_line_0 = "-No Lines-"; string fe_hrs2_v_trans_0 = "-No Lines-"; double fe_hrs2_v_freq_0 = -1.0; bool fe_hrs2_v_usb_0 = true; string fe_hrs3_v_line_0 = "-No Lines-"; string fe_hrs3_v_trans_0 = "-No Lines-"; double fe_hrs3_v_freq_0 = -1.0; bool fe_hrs3_v_usb_0 = true; string fe_hrs4_v_line_0 = "-No Lines-"; string fe_hrs4_v_trans_0 = "-No Lines-"; double fe_hrs4_v_freq_0 = -1.0; bool fe_hrs4_v_usb_0 = true; bool docommands = true; // Whether instrument commands are generated /* Sequence parameters */ int data_time = 4 in [1,20]; // data dump interval limited by the data rates int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_switch_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on ON int n_switch_off = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles on OFF int n_cycles = 1 in [1,1200]; // Number of half OFF-ON-ON-OFF calibration cycles int load_interval = 1800 in [10,7200]; // load period in seconds }{ // start Volkers list {double,double} lineDistance = {0.0,0.0}; int nlines = 1; double stepsize = 0.0; int npoints = 1; double lo_freq = 1000.0; double lo_freq_up = 1000.0; double av_lo_freq = 1000.0; double freq_throw = 0.0; double redundancy_C = 4.0; {double,double} effResolution = {1.0,1.0}; bool continuumDetection = true; {bool,int,double[],bool[]} hrs1 = {true,1,[1.0],[true]}; {bool,int,double[],bool[]} hrs2 = {true,1,[1.0],[true]}; {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // int data_time = 1 ; // double data_chop = 0.0 ; // int n_int_on = 1 ; // int n_int_off = 1 ; // int n_switch_on = 1 ; // int n_switch_off = 1 ; // int n_linesperscan = 1 ; // int n_pointsperscan = 1 ; // int n_freq_point = 1 ; // int n_cycles = 1; // int load_interval = 1 ; // end of Volkers list // start general definitions {int,double,double,double,double,double} result = {1,0.0,0.0,0.0,0.0,0.0}; double degreesPerRadian = 57.2957795; double degreesPerArcmin = 1.0 / 60.0; double degreesPerArcsec = 1.0 / 3600.0; double factorMHzPerGHz = 1000.0; double factorMHzPerkHz = 0.0010; // end general definitions // start translation // frequencies lo_freq = fe_lof_0 * factorMHzPerGHz; if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { lo_freq = lo_freq1 * factorMHzPerGHz; lo_freq_up = lo_freq2 * factorMHzPerGHz; av_lo_freq = 0.5 * (lo_freq + lo_freq_up); } else { av_lo_freq = lo_freq; lo_freq_up = lo_freq; } redundancy_C = double(redundancy); freq_throw = GetTrueFsThrow(band,av_lo_freq,fsThrow); // An additional function is needed here to compute the // actual LO frequency from the redshift correction // This needs to be provided by Mission Planning // double lo_shift=function(redshift,frame,redshiftframe); // pointing stepsize = flyCrossStep * degreesPerArcsec; if(flyNyquistSel) { double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } // Setup for maps if(modeName == "raster" || modeName == "cross" || modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") { // line distance measured 90deg ccw to lines lineDistance = {stepsize * cos(flyAngle / degreesPerRadian),stepsize * -sin(flyAngle / degreesPerRadian)}; npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2); nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1); // exception handling for raster maps if(modeName == "raster") { if(npoints > 32 || nlines > 32) { IError("Map too large." + " Raster maps are restricted to <= 32x32 points."); } } // special treatment for cross map mode if(modeName == "cross") { npoints = 3; nlines = 2; if(crossStepSize == "nyquist") { s = CalibrationReader("beam",["nyquist"],band,av_lo_freq); stepsize = s[0]; } else { s = CalibrationReader("crossstep",[crossStepSize],band,av_lo_freq); stepsize = s[0]; } } } else { npoints = 1; nlines = 1; } // backends // assume none used unless proven otherwise hrs1{0} = false; hrs2{0} = false; wbs1{0} = false; wbs2{0} = false; if(spectrometer == "hrs" || spectrometer == "hrsFast" || spectrometer == "both") { hrs1{0} = true; hrs2{0} = true; } // no HRS in spectral scan modes - only serendipity backend if(modeName == "fs-freq" || modeName == "freq" || modeName == "load-freq") { hrs1{0} = false; hrs2{0} = false; // put minimum resolution explicitely to WBS resolution fe_eff_res_min_0 = max(1.1,fe_eff_res_min_0); } double[] x = CalibrationReader("backendselect",["bestwbs"],band,av_lo_freq); int bestWbs = iround(x[0]); x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,av_lo_freq); int[] stdWbsWindow1 = [iround(x[0]),iround(x[1])]; int[] stdWbsWindow2 = [iround(x[2]),iround(x[3])]; int[] stdWbsWindow3 = [iround(x[4]),iround(x[5])]; int[] stdWbsWindow4 = [iround(x[6]),iround(x[7])]; if(spectrometer == "wbs" || spectrometer == "both") { if(!singleWbs) { wbs1{0} = true; wbs2{0} = true; } else { if(bestWbs == 1) { wbs1{0} = true; } else { wbs2{0} = true; } } } // for spectral scans bool wbs1Used = wbs1{0}; bool wbs2Used = wbs2{0}; string[] hrsModes = ["High","Nominal","Low","Wide"]; if(spectrometer == "hrsFast") { bool[][] hrsUseMap = [[true,false,false,false],[true,false,false,false],[true,true,false,false],[true,true,false,false]]; } else { hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]]; } hrs1{1} = -1; hrs2{1} = -1; for(int i = 0 .. 3) { if(hrsModeH == hrsModes[i]) { hrs1{1} = i; } if(hrsModeV == hrsModes[i]) { hrs2{1} = i; } } // Special treatment for band 6 due to weired definition in HSPOT // Check whether IF is out of subband I if(stdWbsWindow1[1] - stdWbsWindow1[0] == 0) { double mix = 0.8; // mixing point relative to Andrew's scale hrs1{2} = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0]; hrs2{2} = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0]; } else { hrs1{2} = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0]; hrs2{2} = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0]; } for(int j = 0 .. 3) { hrs1{2}[j] = hrs1{2}[j] * factorMHzPerGHz; hrs2{2}[j] = hrs2{2}[j] * factorMHzPerGHz; } hrs1{3} = hrsUseMap[hrs1{1}]; hrs2{3} = hrsUseMap[hrs2{1}]; wbs1{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; wbs2{1} = [stdWbsWindow1,stdWbsWindow2,stdWbsWindow3,stdWbsWindow4]; // resolution effResolution = EffectiveResolution(band,av_lo_freq,{fe_eff_res_min_0,fe_eff_res_max_0},resolutionMhz,wbs1{0},wbs2{0},{hrs1{0},hrs1{1}},{hrs2{0},hrs2{1}}); continuumDetection = dbsContinuum; // no need to translate any sequencer-determined values // end of translation // end of generic code // Start of observing mode OpenMessages("Hifi-Point-FSwitch",{data_time,data_time_off,0,n_switch_on,n_switch_off,0,0,0,n_cycles,load_interval}); // position switch // Call first part of the timing computer {int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int} pre_timing_ps = FSwitch_pre_timing(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_switch_on,n_switch_off,n_cycles,load_interval,docommands); // Prepare telescope command {double,double} onPosition = {ra,dec}; {double,double} refPosition = {raoff,decoff}; {int,int,int,string,int,double,double,bool,double,double,double,int,double,int,int,int,int,int,int} tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,pre_timing_ps,n_cycles); // Dummy call to spacecraft command int[] telescopetimes = nodding_pointing(false,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Call second part of timing computer using results // from telescope command {int,{int,int,int,int,int,int,int,int,int,int,int,int,bool,bool,int,int},int,bool,double,double} post_timing_ps = DoubleChop_post_timing(pre_timing_ps,telescopetimes,n_cycles); // Now the actual observation starts // Prepare telescope command tpar_ps = PositionSwitch_telescope(naifid,onPosition,refPosition,band,lo_freq,post_timing_ps{1},n_cycles); // Call telescope command telescopetimes = nodding_pointing(true,tpar_ps{0},tpar_ps{1},tpar_ps{2},tpar_ps{3},tpar_ps{4},tpar_ps{5},tpar_ps{6},tpar_ps{7},tpar_ps{8},tpar_ps{9},tpar_ps{10},tpar_ps{11},tpar_ps{12},tpar_ps{13},tpar_ps{14},tpar_ps{15},tpar_ps{16},tpar_ps{17},tpar_ps{18},true); // Consistency check int totaltime = post_timing_ps{0}; if(totaltime != telescopetimes[0]) { CError("Mismatch between instrument time of " + totaltime + "s and" + " telescope time of " + telescopetimes[0] + "s detected."); } }{ ////////////////////////////////////////////////////////////////////// // Instrument section // Get all values from post_timing needed in the following ////////////////////////////////////////////////////////////////////// int on_inttime = post_timing_ps{1}{0}; int off_inttime = post_timing_ps{1}{1}; int on_pointing = post_timing_ps{1}{2}; int off_pointing = post_timing_ps{1}{3}; int loadlength = post_timing_ps{1}{4}; int n_loadinterval = post_timing_ps{1}{7}; int n_per_on = post_timing_ps{1}{8}; int n_per_off = post_timing_ps{1}{9}; int n_load_on = post_timing_ps{1}{10}; int n_load_off = post_timing_ps{1}{11}; bool end_load_on = post_timing_ps{1}{12}; bool end_load_off = post_timing_ps{1}{13}; int initshiftlength = post_timing_ps{2}; bool final_load = post_timing_ps{3}; double tscan = post_timing_ps{4}; double tdead = post_timing_ps{5}; ////////////////////////////////////////////////////////////////////// // Now the observation starts for the instrument // Initialize time sync(); int startobs = time(); // Call instrument commands ////////////////////////////////////////////////////////////////////// // Don't do anything if docommand=false // if(docommands) { FSwitch_commanding(band,lo_freq,freq_throw,effResolution,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_loadinterval,n_load_on,n_load_off,end_load_on,end_load_off,final_load,startobs,telescopetimes,loadlength,initshiftlength); } else { delay(telescopetimes[0] + telescopetimes[1]); } // Second consistency check int timeTaken = time() - startobs - telescopetimes[1]; if(timeTaken != totaltime) { CError("Mismatch between instrument time of " + totaltime + "s and" + " command duration of " + timeTaken + "s detected."); } ////////////////////////////////////////////////////////////////////// // Compute the total rms we got out of this // // First get additional dead times from instrument {double,double,double,double,double} tact = DoubleChop_deadtimes("fs",band,lo_freq,hrs1,hrs2,wbs1,wbs2,data_time,data_time_off,n_per_on,n_per_off,n_load_on,n_load_off,tdead); // // Call noise computer {double,double,double,double,double} noisevalues = FSwitch_noisecomputer(band,lo_freq,effResolution,oneGHzReference,on_inttime,off_inttime,n_cycles,tscan,tact); // Evaluate performance DoubleChop_performance(band,lo_freq,effResolution,noisevalues,timeTaken,n_cycles,n_per_on * (n_load_on + 1),n_per_off * (n_load_off + 1),true,tscan,on_pointing,tact); // Return everything noise_level([noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3}]); // Auxiliary construct for HSPOT - return total time and noise values // Also return the maximum ratio of drift to radiometric noise return {timeTaken,noisevalues{0},noisevalues{1},noisevalues{2},noisevalues{3},noisevalues{4}}; } // Change LO frequency by a small step in FSW mode // // Externally it has to be guaranteed that this never uses a step larger // than one index in the LO table procedure HIFIChangeFreqFsw { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency ion MHz double freq_throw = -40.0; // throw of frequency switch in MHz }{ ConfigureFPU(band,lo_freq + freq_throw / 2.0,false); HIFITuneFreqNoretuneFsw(band,lo_freq,lo_freq + freq_throw); } ///////////////////////////////////////////////////////////////////////////// // Procedure to perform the noise level evaluation for the OTF observing mode {double,double,double,double,double} procedure OTFmap_noisecomputer { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF int nlines_tot = 1; // Number of rows in the map int npoints = 10; // Number of data dumps per row int n_supersample = 1; // Supersamplingfactor int n_linesperscan = 2; // Number of lines between two OFFs int n_cover = 1; // Number of map coverages int tslew = 20; // Minimum time between OFF and point double tscan = 60.0; // Total average duration of one scan {double,double,double} tact = {10.0,4.0,12.0}; // field of actual timings }{ // The sum of drift noise and radiometric noise is computed. // double tdead = tact{0}; // Average dead time in one slew double tint_act = tact{1}; // integration time excluding all dead times double tintoff = tact{2}; // integration time on OFF // Get parameters which are needed double tsys = InterpolateTsys(band,lo_freq); double eta_mb = InterpolateCoupling(band,lo_freq); double[] gssb = InterpolateGssb(band,lo_freq); // Get the drift parameters to compute the drift noise double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / eff_resolution{1},binningexp); double allan_time_hires = allanparms[0] * pow(1.0 / eff_resolution{0},binningexp); // Noise computation and OFF integration depends on the number of really // independent points - different treatment for repeated scans of same line double scanpoints = double(n_linesperscan * npoints); double qval = tintoff / (sqrt(scanpoints) * tint_act); if(nlines_tot == 1 && n_linesperscan > 1) { // Get actual noise // This is returned twice: for both limiting resolutions double systemnoise_lores = OtfRepeatedNoise(double(n_linesperscan),scanpoints,[tint_act / allan_time_lores,tdead / allan_time_lores,double(tslew) / allan_time_lores,qval,alpha]); double systemnoise_hires = OtfRepeatedNoise(double(n_linesperscan),scanpoints,[tint_act / allan_time_hires,tdead / allan_time_hires,double(tslew) / allan_time_hires,qval,alpha]); double noiserat = OtfRepeatedNoiseRatio(double(n_linesperscan),scanpoints,[tint_act / allan_time_lores,tdead / allan_time_lores,double(tslew) / allan_time_lores,qval,alpha]); } else { // Get actual noise systemnoise_lores = OtfNoise(scanpoints,[tint_act / allan_time_lores,tdead / allan_time_lores,double(tslew) / allan_time_lores,qval,alpha]); systemnoise_hires = OtfNoise(scanpoints,[tint_act / allan_time_hires,tdead / allan_time_hires,double(tslew) / allan_time_hires,qval,alpha]); noiserat = OtfNoiseRatio(scanpoints,[tint_act / allan_time_lores,tdead / allan_time_lores,double(tslew) / allan_time_lores,qval,alpha]); } // Renormalize systemnoise_lores = systemnoise_lores * scanpoints / (tscan * double(n_cover)); systemnoise_hires = systemnoise_hires * scanpoints / (tscan * double(n_cover)); // Compute total double sideband noise double dsbnoise_lores = tsys * sqrt(systemnoise_lores / (eff_resolution{1} * 1000000.0)); double dsbnoise_hires = tsys * sqrt(systemnoise_hires / (eff_resolution{0} * 1000000.0)); // Translate to the main beam scale, correct for eta_mb // (This is typically not done at ground based telescopes, // but leads often to problems there - to be discussed.) dsbnoise_lores = dsbnoise_lores / eta_mb; dsbnoise_hires = dsbnoise_hires / eta_mb; // Get single sideband noise equivalent double usbnoise_lores = dsbnoise_lores / gssb[0]; double usbnoise_hires = dsbnoise_hires / gssb[0]; double lsbnoise_lores = dsbnoise_lores / gssb[1]; double lsbnoise_hires = dsbnoise_hires / gssb[1]; // Return noise values and the maximum ratio of drift to radiometric noise return {usbnoise_lores,usbnoise_hires,lsbnoise_lores,lsbnoise_hires,noiserat}; } // procedure called to get the WBS into standby procedure HifiIntoStandby_II { }{ //LO is switched off -> is superfluous if from stbyI to stbyII LCU_switch_off_block_aot(); //LO is switched to standby -> is superfluous if from stbyI to stbyII LCU_standby_block_aot(); //FPU stand-by: HBB is ON, chopper to rest position Init_MSA_aot("0","CLOSE",0.0,true,"ON"); //HRS stand-by -> is superfluous if from stbyI to stbyII HRS_config_max_att_block_aot("0",["wb","wb"]); //WBS stand-by with laser ON WBS_standby_block_aot("ON"); } // Generic A_M function // DT/MB - 3 June 2005 int[] procedure GetA_M { double flo = 15.0; // Input HRS internal LO freq. in GHz }{ // First guess of M int m = iround(flo / 200.0 - 1.0); int a = iround((flo - 200.0 * (double(m) + 1.0)) / 20.0); // // Adjust if(a < 0) { m = m - 1; a = iround((flo - 200.0 * (double(m) + 1.0)) / 20.0); } // int[] a_m = [a,m]; return a_m; } //////////////////////////////////////////////////////////////////////////// // Procedure to generate the instrument commands for the OTF observing mode procedure OTFLoadChop_commanding { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} eff_resolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4; // chunk size given by the data rates and optimum speed int data_time_off = 4 in [1,20]; // data dump interval on OFF int n_perline = 10; // Number of frequency switch cycles per line int n_switch_off = 3; // Number of frequency switch cycles on OFF int nlines_tot = 1; // Total number of lines to scan int n_linesperscan = 1; // Number of lines between two OFFs int n_loadinterval = 1; // number of nods before a load measurement int startobs = 0; // Actual starting time of observation int[] telescopetimes = [300,180,2,2,40,10,20,21,0]; // Timing of the observation from telescope int loadlength = 21; // Load duration }{ // Auxiliary variables // Create a composite readout structure for simpler handling {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // get time values from the telescope structure int tinitslew = telescopetimes[1]; // Initial slew time int toffslew = telescopetimes[6]; // slew dead time between points //////////////////////////////////////////////////////////////////////// // Instrument Initialization: The instrument tuning is done as early as // possible, the load calibration as late as possible // // Clustering is currently not implemented in MPS - switched off here int clustered = 0; // data rates {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); double[] onrates = dataparms{1}; dataparms = DataTaking(backendreadoutparms,data_time_off); double[] offrates = dataparms{1}; int hkduration = HkReadoutTime(band,lo_freq,backendreadoutparms,false); int readoutdead = SlowChopReadoutDelay(band,lo_freq,backendreadoutparms); // Count OFFs by hand, their counter is not returned in the state array int ioff = 0; //////////////////////////////////////////////////////////////////////// // start state machine int[] state = [0]; while(state[0] >= 0) { state = next_state(); if(state[0] == 1) { // Initialization if(clustered != 1) { HIFIInitObs(); TuneHIFI(band,lo_freq,hrs1,hrs2,wbs1{0},wbs2{0},"normal"); } delay(tinitslew - (time() - startobs) - loadlength - hkduration); // First load measurement HIFISetHK("normal",false); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 4) { // OFF Integration HIFIConfigureLoadChopIntegration(data_time_off,n_switch_off,band,lo_freq,backendreadoutparms); HIFILoadChopOffIntegration(data_time_off,n_switch_off,band,lo_freq,offrates); // OFF counter ioff = ioff + 1; // Check for normal slew after OFF if(state[2] * state[3] < nlines_tot) { HIFIActiveHK("normal",toffslew); } } if(state[0] == 8) { // OTF integration // Check whether we come from the OFF if((state[2] + n_linesperscan - 1) % n_linesperscan == 0) { HIFIConfigureLoadChopIntegration(data_time,n_perline,band,lo_freq,backendreadoutparms); } HIFILoadChopOnIntegration(data_time,n_perline,band,lo_freq,onrates); // Check for normal slew towards the OFF if(state[2] % n_linesperscan == 0) { if(ioff % n_loadinterval > 0) { HIFIActiveHK("normal",toffslew); } } } if(state[0] == 9) { // Load slew delay(readoutdead); LoadMeasurement(band,lo_freq,eff_resolution{0},data_time,backendreadoutparms); } if(state[0] == 5) { delay(readoutdead); HIFICloseObs(); } } } // HRS partial configuration, procedure // Configures the resolution mode procedure HRS_config_resol_fm { string band = "4a"; // HIFI band string[] hrs_mode = ["wb","wb"]; //HRS resolution code }{ //////////////////////////////////////////////////////////////////// //Now Configure blocks //H-polar string hrs_filename_h = "name_confighrs_" + hrs_mode[0]; {double,string}[] result = ConfigurationReader(hrs_filename_h,["hrh_block_1","hrh_block_2","hrh_block_3","hrh_block_4","hrh_block_5","hrh_block_6","hrh_block_7","hrh_block_8"],band,0.0); string hrh_block_1 = result[0]{1}; string hrh_block_2 = result[1]{1}; string hrh_block_3 = result[2]{1}; string hrh_block_4 = result[3]{1}; string hrh_block_5 = result[4]{1}; string hrh_block_6 = result[5]{1}; string hrh_block_7 = result[6]{1}; string hrh_block_8 = result[7]{1}; // result = ConfigurationReader("name_delays",["hrs_config_delay"],band,0.0); int hrs_config_delay = iround(result[0]{0}); // Hifi_HIFI_Config_HRS_H_blocks($BBID,hrh_block_1,hrh_block_2,hrh_block_3,hrh_block_4,hrh_block_5,hrh_block_6,hrh_block_7,hrh_block_8); //delay(hrs_config_delay); // //V-polar string hrs_filename_v = "name_confighrs_" + hrs_mode[1]; result = ConfigurationReader(hrs_filename_v,["hrv_block_1","hrv_block_2","hrv_block_3","hrv_block_4","hrv_block_5","hrv_block_6","hrv_block_7","hrv_block_8"],band,0.0); string hrv_block_1 = result[0]{1}; string hrv_block_2 = result[1]{1}; string hrv_block_3 = result[2]{1}; string hrv_block_4 = result[3]{1}; string hrv_block_5 = result[4]{1}; string hrv_block_6 = result[5]{1}; string hrv_block_7 = result[6]{1}; string hrv_block_8 = result[7]{1}; // Hifi_HIFI_Config_HRS_V_blocks($BBID,hrv_block_1,hrv_block_2,hrv_block_3,hrv_block_4,hrv_block_5,hrv_block_6,hrv_block_7,hrv_block_8); // //Wait delay to allow all setting to be configured delay(hrs_config_delay); } // Single integration at OFF position for a specified time block HIFIContOffIntegration HIFI 6021 { int n_int = 1; // Integration time counter int data_time = 4; // Integration time between two data readouts double[] rates = [120.0,1.0,2.0]; // Data rates between and during integrations }{ HIFI_Spectr_tp_proc_aot(n_int,data_time,rates); } // Interpolate total power system Allan time and exponent double[] procedure InterpolateTpAllan { string band = "4a"; // HIFI band double lo_freq = 978200.0; // LO frequency bool subband = false; // 1GHz bandwith reference instead of full IF }{ if(subband) { double[] allan = CalibrationReader("system_Allan_subband",["tp_Allan_time","tp_Allan_exp","tp_binning_exp"],band,lo_freq); } else { allan = CalibrationReader("system_Allan",["tp_Allan_time","tp_Allan_exp","tp_binning_exp"],band,lo_freq); } return allan; } ///////////////////////////////////////////////////////////////// // Procedure to compute detailed timing for a // Spectral Scan Load-chop observing mode // {{int,int,int,int,int,int,bool,int,int},{int,double,double[],int[][],bool,double[],int,bool}} procedure SScanLoadChopNoRef_pre_timing { string band = "4a"; // HIFI band double lo_freq_low = 978200.0; // Lower LO frequency limit in MHz double lo_freq_up = 979600.0; // Upper LO frequency limit in MHz int redundancy = 4; // Frequency scan redundancy {double,double} eff_resolution = {1.1,1.1}; // Minimum and maximum goal resolution of the calibrated data in MHz {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} int data_time = 4 in [1,20]; // data dump interval limited by the data rate/stability int n_chop_on = 2 in [1,900]; // number of half nu1-nu2-nu2-nu1 cycles per frequency and pointing int n_freq_point = 1 in [1,12]; // Number of frequency steps before pointing to second phase int load_interval = 1800 in [10,7200]; // load period in seconds bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Create composite readout structure for backends {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; // Get frequency grid characteristic parameters {int,double,double[],int[][],int,bool} fqparms = MakeFreqGrid(band,lo_freq_low,lo_freq_up,redundancy,0.0,n_freq_point); int groupnumber = fqparms{0}; double reffreq = fqparms{1}; double[] freqgrid = fqparms{2}; int[][] grouporder = fqparms{3}; // Process tuning level grid double[][] levelgrid = GetSScanLevelGrid(band,wbs1,wbs2,freqgrid,fqparms{0},grouporder); {bool,double[]} targets = TargetLevels(band,reffreq,levelgrid); bool retuning = targets{0}; double[] targetgrid = targets{1}; string reftarget = ""; if(retuning) { reftarget = "sscan_normal"; } {int,double,double[],int[][],bool,double[],int,bool} spectralparms = {fqparms{0},reffreq,freqgrid,grouporder,retuning,targetgrid,fqparms{4},fqparms{5}}; ////////////////////////////////////////////////////////////////////// int jitterdead = GetMaxTimeJitter(band,reffreq); // Integration time per frequency and pointing int on_inttime = 2 * n_chop_on * data_time; // Tuning delays int bigtunestep = duration(HIFIRetuneFreq(band,reffreq,reftarget)); // Correct for variation within the band int tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq); bigtunestep = bigtunestep + tunediff; // A step within a group could be faster than a large step if(n_freq_point > 1) { int smallstep = duration(HIFIChangeFreq(band,reffreq)); } else { smallstep = bigtunestep; } int grouptime = n_freq_point * on_inttime + (n_freq_point - 1) * smallstep; // Compute load integration time int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms)); int readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms); loadlength = loadlength + readoutdead; // Duration of initial set up // Staying at the same frequency makes no sense here. // First frequency point double runningfreq = freqgrid[grouporder[0][0]]; // determine exact duration only in case of full commanding if(docommands) { int initlength = duration(HIFIInitObs()); initlength = initlength + duration(TuneHIFI(band,runningfreq,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal")); // Add time for HK readout int hkduration = HkReadoutTime(band,reffreq,backendreadoutparms,false); initlength = initlength + hkduration; } else { initlength = GetRoughInitLength(band,runningfreq,true); } initlength = initlength + loadlength; int initloadlength = loadlength; // Compare load interval with duration of the observation int load_spacing = CheckedLoadSpacing(load_interval - loadlength,8); if(load_spacing < grouptime && n_freq_point > 1) { SError("Load period too short for frequency group size."); } // Here we bracket each cycle by loads, this leads to a grace period int n_load_on = on_inttime / load_spacing; // In the following the definition of n_load_on is higher by 1 relative to // that used in normal load-chop! // This determines the order of the loops if(n_load_on == 0) { int n_per_on = n_chop_on; bool end_load_on = false; // recompute load length in case of short integrations loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,false,eff_resolution{0},data_time,backendreadoutparms)); loadlength = loadlength + readoutdead; } else { // grace condition if(double(on_inttime) > 1.2 * double(load_spacing)) { n_load_on = n_load_on + 1; } n_per_on = n_chop_on / n_load_on; if(n_per_on < 1) { SError("FS phase length on source too long relative to load period."); } end_load_on = true; on_inttime = 2 * n_per_on * n_load_on * data_time; // This cannot happen for n_freq_point > 1 grouptime = on_inttime + n_load_on * loadlength; } int on_pointing = groupnumber * (grouptime + bigtunestep + loadlength) - bigtunestep - loadlength + jitterdead; // dangling time given by readout dead time int dangling = readoutdead; // Return all the times needed for telescope call and post_timing processing return {{on_inttime,on_pointing,initloadlength,load_spacing,n_per_on,n_load_on,end_load_on,initlength,dangling},spectralparms}; } //////////////////////////////////// // OTF load chop observing mode without baseline calibration // {string,double,double}[] procedure HifiMappingProcLoadChopOTFNoRefSequencerInit { /* Setup parameters */ int naifid = 0; // Tracking object ID double ra = 0.0; // RA coordinate of the source double dec = 0.0; // DEC coordinate of the source {double,double} lineDistance = {0.0050,0.0050}; // Distance between subsequent rows int nlines = 1 in [1,240]; // Number of rows in the map double stepsize = 0.0050 in [0.0,0.13333]; // Distance between subsequent points in the OTF line int npoints = 10 in [1,720]; // Number of data dumps per row string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band double lo_freq = 978200.0; // LO frequency in MHz {double,double} effResolution = {1.0,1.0}; // Minimum and maximum goal resolution of the calibrated data in MHz bool oneGHzReference = true; // 1GHz reference bandwith instead of full IF {bool,int,double[],bool[]} hrs1 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS1 parameters={used,resolution,frequency offsets, subbands used} {bool,int,double[],bool[]} hrs2 = {true,1,[-110.0,110.0,0.0,0.0],[true,true,true,true]}; // HRS2 parameters={used,resolution,frequency offsets, subbands used} {bool,int[][]} wbs1 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS1 parameters ={used, channel windows} {bool,int[][]} wbs2 = {true,[[0,2048],[0,2048],[0,2048],[0,2048]]}; // WBS2 parameters ={used, channel windows} /* Sequence parameters */ int data_time = 4 in [1,20]; // chunk size given by the data rates and optimum speed int n_switch_on = 1 in [1,1800]; // Supersamplingfactor int n_cycles = 1 in [1,1200]; // Number of map coverages int load_interval = 1800 in [10,7200]; // load period defines number of lines between two loads bool docommands = false; // Whether instrument command loop is executed }{ ////////////////////////////////////////////////////////////////////// // Start of observing mode // limit on data rate {{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = {{hrs1{0},hrs1{1},hrs1{3}},{hrs2{0},hrs2{1},hrs2{3}},wbs1,wbs2}; {int,double[]} dataparms = DataTaking(backendreadoutparms,data_time); int datalimit = dataparms{0}; // limits from noise section // Get the drift parameters to compute the drift noise // System Allan variance double[] allanparms = InterpolateSpecAllan(band,lo_freq,oneGHzReference); // rescale to frequency resolution double alpha = allanparms[1]; double binningexp = 1.0 / allanparms[2]; double allan_time_lores = allanparms[0] * pow(1.0 / effResolution{1},binningexp); // Compute derived quantities int data_time_guess = imin(imax(iceil(0.3 * allan_time_lores),datalimit),20); int data_time_range = datalimit - data_time_guess; if(data_time_range == 0) { data_time_range = 1; } // n_switch limited by load_interval - 2 lines should be possible int n_switch_on_guess = load_interval / (4 * npoints * data_time_guess); int n_switch_on_range = 1 - n_switch_on_guess; if(n_switch_on_range == 0) { n_switch_on_range = 1; } // Contruct return tuple {string,double,double}[] retvalues = [{"data_time",double(data_time_guess),double(data_time_range)},{"n_switch_on",double(n_switch_on_guess),double(n_switch_on_range)}]; return retvalues; } ////////////////////////////////////////////////////////////////// // HRS complete configuration with maximum attenuation, block // Both polarizations are treated block HRS_config_max_att_block_aot HIFI 6634 { string band = "4a"; // HIFI band string[] hrs_mode = ["wb","wb"]; //HRS resolution code }{ // Fetch HRS configuration parameters //=================================== //H-polar string hrs_filename_h = "name_confighrs_" + hrs_mode[0]; {double,string}[] result = ConfigurationReader(hrs_filename_h,["hrh_switch","hrh_1u_att","hrh_1l_att","hrh_2u_att","hrh_2l_att","hrh_3u_att","hrh_3l_att","hrh_4u_att","hrh_4l_att","hrh_up_ol1","hrh_up_ol2","hrh_up_ol3","hrh_up_ol4","hrh_down_ol5","hrh_down_ol6","hrh_down_ol7"],band,0.0); string hrs_polarization_h = result[0]{1}; double[] hrsH_LO = [result[9]{0},result[10]{0},result[11]{0},result[12]{0},result[13]{0},result[14]{0},result[15]{0}]; //V-polar string hrs_filename_v = "name_confighrs_" + hrs_mode[1]; result = ConfigurationReader(hrs_filename_v,["hrv_switch","hrv_1u_att","hrv_1l_att","hrv_2u_att","hrv_2l_att","hrv_3u_att","hrv_3l_att","hrv_4u_att","hrv_4l_att","hrv_up_ol1","hrv_up_ol2","hrv_up_ol3","hrv_up_ol4","hrv_down_ol5","hrv_down_ol6","hrv_down_ol7"],band,0.0); string hrs_polarization_v = result[0]{1}; double[] hrsV_LO = [result[9]{0},result[10]{0},result[11]{0},result[12]{0},result[13]{0},result[14]{0},result[15]{0}]; // result = ConfigurationReader("name_delays",["hrs_config_delay"],band,0.0); int hrs_config_delay = iround(result[0]{0}); //Convert IF frequencies into A and M parameters //Truncate wb or hr keyword: string[] output_hrs_mode = GetHrsMode_proc_fm(hrs_mode); string hrs_mode_h = output_hrs_mode[0]; string hrs_mode_v = output_hrs_mode[1]; // int[] a_m_parameter = ComputeA_M_parameters([hrs_mode_h,hrs_mode_v],hrsH_LO[0],hrsH_LO[1],hrsH_LO[2],hrsH_LO[3],hrsH_LO[4],hrsH_LO[5],hrsH_LO[6],hrsV_LO[0],hrsV_LO[1],hrsV_LO[2],hrsV_LO[3],hrsV_LO[4],hrsV_LO[5],hrsV_LO[6]); //H-polar int hrh_up_ol1_m = a_m_parameter[1]; int hrh_up_ol1_a = a_m_parameter[0]; int hrh_up_ol2_m = a_m_parameter[3]; int hrh_up_ol2_a = a_m_parameter[2]; int hrh_up_ol3_m = a_m_parameter[5]; int hrh_up_ol3_a = a_m_parameter[4]; int hrh_up_ol4_m = a_m_parameter[7]; int hrh_up_ol4_a = a_m_parameter[6]; int hrh_down_ol5_m = a_m_parameter[9]; int hrh_down_ol5_a = a_m_parameter[8]; int hrh_down_ol6_m = a_m_parameter[11]; int hrh_down_ol6_a = a_m_parameter[10]; int hrh_down_ol7_m = a_m_parameter[12]; //V-polar int hrv_up_ol1_m = a_m_parameter[14]; int hrv_up_ol1_a = a_m_parameter[13]; int hrv_up_ol2_m = a_m_parameter[16]; int hrv_up_ol2_a = a_m_parameter[15]; int hrv_up_ol3_m = a_m_parameter[18]; int hrv_up_ol3_a = a_m_parameter[17]; int hrv_up_ol4_m = a_m_parameter[20]; int hrv_up_ol4_a = a_m_parameter[19]; int hrv_down_ol5_m = a_m_parameter[22]; int hrv_down_ol5_a = a_m_parameter[21]; int hrv_down_ol6_m = a_m_parameter[24]; int hrv_down_ol6_a = a_m_parameter[23]; int hrv_down_ol7_m = a_m_parameter[25]; //Attenuators are fixed //H-polar double hrh_1u_att = 15.5; double hrh_1l_att = 15.5; double hrh_2u_att = 15.5; double hrh_2l_att = 15.5; double hrh_3u_att = 15.5; double hrh_3l_att = 15.5; double hrh_4u_att = 15.5; double hrh_4l_att = 15.5; //V-polar double hrv_1u_att = 15.5; double hrv_1l_att = 15.5; double hrv_2u_att = 15.5; double hrv_2l_att = 15.5; double hrv_3u_att = 15.5; double hrv_3l_att = 15.5; double hrv_4u_att = 15.5; double hrv_4l_att = 15.5; //Configure HRS-H Hifi_HIFI_Config_HRS_H_att_lo($BBID,hrs_polarization_h,hrh_1u_att,hrh_1l_att,hrh_2u_att,hrh_2l_att,hrh_3u_att,hrh_3l_att,hrh_4u_att,hrh_4l_att,hrh_up_ol1_m,hrh_up_ol1_a,hrh_up_ol2_m,hrh_up_ol2_a,hrh_up_ol3_m,hrh_up_ol3_a,hrh_up_ol4_m,hrh_up_ol4_a,hrh_down_ol5_m,hrh_down_ol5_a,hrh_down_ol6_m,hrh_down_ol6_a,hrh_down_ol7_m); //delay(hrs_config_delay); // //Configure HRS-V Hifi_HIFI_Config_HRS_V_att_lo($BBID,hrs_polarization_v,hrv_1u_att,hrv_1l_att,hrv_2u_att,hrv_2l_att,hrv_3u_att,hrv_3l_att,hrv_4u_att,hrv_4l_att,hrv_up_ol1_m,hrv_up_ol1_a,hrv_up_ol2_m,hrv_up_ol2_a,hrv_up_ol3_m,hrv_up_ol3_a,hrv_up_ol4_m,hrv_up_ol4_a,hrv_down_ol5_m,hrv_down_ol5_a,hrv_down_ol6_m,hrv_down_ol6_a,hrv_down_ol7_m); delay(hrs_config_delay); // //Now Configure blocks HRS_config_resol_fm(band,hrs_mode); } //TM to control FDIR on LOU temp. block Set_LO_FDIR_temperature_block_aot HIFI 3953 { }{ // BBID needs to be set manually as the main TC command has no BBID argument Hifi_HIFI_Set_OBS_ID($BBID,$OBSID); //Fetch values to apply: band-independent so far double[] cresult = CalibrationReader("name_loheater",["tmin","tmax","nbreach"],"1a",0.0); double tmin = cresult[0]; //Min threshold double tmax = cresult[1]; //Max threshold int nbreach = iround(cresult[2]); //Number of breach // // removed temporarily to guarantee compatibility with old MIB for phase3 // Hifi_HIFI_LOU_T_check_on(nbreach,tmax,tmin); delay(1); // } //TM to control heater values of LOU, procedure procedure HL_heater_proc_aot { string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band. string context = "nominal" in ["nominal","stby"]; //whether heater applies to stby or nominal context }{ double[] cresult = CalibrationReader("name_loheater",["heater_nominal","heater_stby"],band,0.0); double hifi_HL_heater = cresult[0]; if(context == "stby") { hifi_HL_heater = cresult[1]; } Hifi_HIFI_HL_heater($BBID,hifi_HL_heater); } // Routine to check whether loadlength is short compared to // load interval, so that loadspacing is reasonably long int procedure CheckedLoadSpacing { int load_spacing = 100; // time interval between load measurements int minspacing = 8; // minimum interval }{ if(load_spacing < minspacing) { IError("Required load calibration time too long. " + "Increase lower goal resolution limit."); } return load_spacing; }