// 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
int tline = telescopetimes[4];
// Time in line
// The telescope slew can be a bit further than requested
int line_inttime = n_pp * data_time;
{int,int} otfline = OtfTelescopeLine(line_inttime,tline);
int line_startdelay = otfline{1};
////////////////////////////////////////////////////////////////////////
// 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
delay(line_startdelay);
// 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};
}
//Upload of LCU safety tables in MTL
obs HifiEng_upload_LCU_table_MTL {
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(LcuSafetyTableUpload_fm(0,9999));
// 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) {
// Test execution
LcuSafetyTableUpload_fm(0,9999);
}
if(state[0] == 5) {
//HIFISetHK("normal",true); // -> superfluous
HIFICloseObs();
}
}
}
// HBB Response time, procedure
procedure HBB_Response_time_proc_fm {
}{
error("Cannot be used in warm context");
//
//It just configures the FPU, setting the HBB at the required temp.
//Then we just wait for the temperature to stabilize to the final value...
//For the sake of simplicity, we use Band0 parameters.
Band0_hbb_on_fm("0","CLOSE");
//
}
//Heater setting in manual commanding
mode HifiManCmd_Set_HL_Heater {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure for LOU heater setting adjustement");
StartMode_block_ops();
//
mois_step("Set heater voltage");
mois_spacon("In the next TC, the heater voltage HP397194 should be treated as an FP");
HL_heater_block_fm("1a","stby");
//
StopMode_block_mois();
// -> to issue last obsd/bbid
}
// IV curve, block
block IVcurve_pumped_fm HIFI 3213 {
string band = "1a";
double lo_freq = 522.0; //LO frequency
}{
//Start_block() ;
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["bias_min_h","bias_max_h","bias_steps_h","bias_min_v","bias_max_v","bias_steps_v"],band,0.0);
//H polar
double bias_min_h = result_d[0]{0};
double bias_max_h = result_d[1]{0};
int steps_h = iround(result_d[2]{0});
//V polar
double bias_min_v = result_d[3]{0};
double bias_max_v = result_d[4]{0};
int steps_v = iround(result_d[5]{0});
//Nominal bias set at the end
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};
double magnetcurrent_h = 0.0;
double magnetcurrent_v = 0.0;
//
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
result_d = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v"],band,lo_freq);
magnetcurrent_h = result_d[0]{0};
magnetcurrent_v = result_d[1]{0};
}
//
//The IVCurve is done on the smallest range and the finest step
double bias_min = max(bias_min_h,bias_min_v);
double bias_max = min(bias_max_h,bias_max_v);
int steps = iround(max(double(steps_h),double(steps_v)));
//
//First set magnets to max.
double magnet_current_max_h = 0.0;
double magnet_current_max_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,0.0);
magnet_current_max_h = result_d[0]{0};
magnet_current_max_v = result_d[1]{0};
}
Hifi_HIFI_CH1_MX_MG_C($BBID,magnet_current_max_h);
Hifi_HIFI_CV1_MX_MG_C($BBID,magnet_current_max_v);
delay(1);
//Perform IV curve
IVcurve(band,bias_min,bias_max,steps,magnetcurrent_h,magnetcurrent_v,bias_h,bias_v);
}
//Notify PDU status OFF, procedure
procedure HIFI_notify_PDU_status_off_proc_ops {
string status_FCU = "OFF" in ["ON","OFF"]; //Status of FCU
string status_LCU = "OFF" in ["ON","OFF"]; //Status of LCU
string status_WBSV = "OFF" in ["ON","OFF"]; //Status of WBSV
string status_WBSH = "OFF" in ["ON","OFF"]; //Status of WBSH
string status_HRSV = "OFF" in ["ON","OFF"]; //Status of HRSV
string status_HRSH = "OFF" in ["ON","OFF"]; //Status of HRSH
}{
Hifi_HIFI_notify_PDU_status(status_FCU,status_LCU,status_WBSV,status_WBSH,status_HRSV,status_HRSH);
//Prepare message for operator: we will check whether one particular HK is ON
if(status_FCU == "OFF") {
string subsyst_off = "HI_FCU_S";
}
if(status_WBSH == "OFF") {
subsyst_off = "HI_WBSH_S";
}
if(status_WBSV == "OFF") {
subsyst_off = "HI_WBSV_S";
}
if(status_HRSH == "OFF") {
subsyst_off = "HI_HRSH_S";
}
if(status_HRSV == "OFF") {
subsyst_off = "HI_HRSV_S";
}
if(status_LCU == "OFF") {
subsyst_off = "HI_LCU_S";
}
mois_tmcheck("Check that the HK parameter " + subsyst_off + " is OFF.");
delay(1);
}
//Peak test configuration, block
block Peakup_test_configure_block_fm HIFI 3820 {
string band = "1" in ["1","2","3","4","5","6","7"]; // HIFI band
string mixer_polarization = "H" in ["H","V"]; //mixer polarization to be used
}{
//Start_block();
//Get offset of observed aperture wrt band 6H
string tab = "peakup_offset.config";
double peakup_scale_y = dlookup(tab,"" + band,"scale_y");
double peakup_scale_z = dlookup(tab,"" + band,"scale_z");
double offset_y = dlookup(tab,"" + band,"offset_y_H");
double offset_z = dlookup(tab,"" + band,"offset_z_H");
if(mixer_polarization == "V") {
offset_y = dlookup(tab,"" + band,"offset_y_V");
offset_z = dlookup(tab,"" + band,"offset_z_V");
}
//
Hifi_HIFI_configure_peakup_r1($BBID,iround(peakup_scale_y),iround(peakup_scale_z),iround(offset_y),iround(offset_z));
//no delay ? tests with fm_cus_12.7 show that 1sec may be not enough
delay(2);
}
// 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("Noise values are given at this frequency for the single-sideband" + " deconvolution product, and the double-sideband pipeline " + "products for individual LO settings on a " + "polarization-averaged, " + "single-sideband, main beam temperature scale of a " + fwhm + "'' beam with a main beam efficiency of " + eta_mb * 100.0 + "%.", 1);
} else {
message("Noise values are given on a polarization-averaged," + " single-sideband, main beam temperature scale of a " + fwhm + "'' beam with a main beam efficiency of " + eta_mb * 100.0 + "%.", 1);
}
message("
");
}
// Second part of FPSS FM functional test, block
// Check cryogenic health
block FT_FPU_check_cryohealth_fm HIFI 3801 {
string band = "1a";
int integ_time = 4; //Integation time in seconds
double lo_freq = 500.0; //LO frequency
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//We will check the IF noise
// Backends are required !!
//We assume the bias voltage is already at its
//normal value
//Get magnets in case band 1-5 is used
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
{double,string}[] result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,0.0);
//
//Set magnet to max. for hysteresis issues
Hifi_HIFI_CH1_MX_MG_C($BBID,result[0]{0});
Hifi_HIFI_CV1_MX_MG_C($BBID,result[1]{0});
delay(1);
}
//Get nominal biases and magnets
result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v","norm_magn_h","norm_magn_v"],band,lo_freq);
double bias_h = result[0]{0};
double bias_v = result[1]{0};
double magnet_current_h = result[2]{0};
double magnet_current_v = result[3]{0};
//
Hifi_HIFI_FCU_parameter_scan($BBID,1,1,0.1,bias_h,bias_v,0.0,magnet_current_h,magnet_current_v,0.0);
//Sets magnet current
delay(2);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//
//Perform IF noise test
result = ConfigurationReader("name_confilfpu",["bias_low_resistive_h","bias_low_resistive_v","bias_high_resistive_h","bias_high_resistive_v"],band,0.0);
//1. bias 5 Volts
bias_h = result[0]{0};
bias_v = result[1]{0};
//
Hifi_HIFI_FCU_parameter_scan($BBID,1,1,0.1,bias_h,bias_v,0.0,0.0,0.0,0.0);
//Sets magnet current to 0
delay(2);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//
//Perform IF noise test
//2. bias 10 Volts
bias_h = result[2]{0};
bias_v = result[3]{0};
//
Hifi_HIFI_FCU_parameter_scan($BBID,1,1,0.1,bias_h,bias_v,0.0,0.0,0.0,0.0);
//Sets magnet current to 0
delay(2);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//
}
//HIFI measurement of HEB spectra variation vs Imix, mode
//Takes spectra over the full Vd2 range
obs HifiEng_HEB_Spectra_vs_Imix_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
bool lo_chain_switch = false; //Whether the chain is already switched on
int testtime = 900; //total time we want to spend on testing
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(HEB_Spectra_vs_Imix_proc_fm_COP(band,lo_chain_switch,testtime));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
HEB_Spectra_vs_Imix_proc_fm_COP(band,lo_chain_switch,testtime);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
//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
}{
//
}
// Integrate only on external cold, block
// We take 1 spectrum per phase.
block Stability_extcold_fm HIFI 3437 {
string band = "1a"; // HIFI band
int n = 100; //The number of integrations
int integ_time = 4; //Total integration time in sec. to be set at end of test
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
string obsmode = "fastchop" in ["fastchop","tp"]; //tp or fastchop
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length
}{
Start_block();
Chopper_Rotation_proc_fm(band,"chop_hot_ang","chop_M3_ang");
//Look at M3
//Get chopper settings
{double,string}[] result = ConfigurationReader("name_confilfpu",["chop_M3"],band,0.0);
double chop_M3 = result[0]{0};
//Close shutter
//Shutter_rotate_proc_fm("closed");
//Do a long integration
// - for B1-5, use 2 sec. with wbs or hrs only, thus tp is OK
// - for B6: use 1 sec. with reduced wbs (wbsFast), thus tp is OK
//We implement a special spectroscopy configuration with fixed values
if(obsmode == "tp") {
Total_power_spectro_for_Stability_proc_fm(band,n,integ_time,backend,hrs_mode);
}
if(obsmode == "fastchop") {
Fast_chop_spectro_for_Stability_proc_fm(band,n,integ_time * 2,backend,hrs_mode,chop_M3,chop_M3,chop_phase);
}
}
//DEPRECATED. USE OBS COMMAND INSTEAD
// WBS zero, procedure
// This is a work-around for WBS_Zero.
//procedure WBS0_fm_proc {
// string band="1a"; // HIFI band
// }{
// Hifi_HIFI_Single_cmd ($BBID, "HWH_ZERO_ON");
// Hifi_HIFI_Single_cmd ($BBID, "HWV_ZERO_ON");
// delay (1) ;
// //Configure spectroscopy
// {double, string}[] result_d = ConfigurationReader("name_delays",
// ["integ_time_zero"],band,0.0);
// int integ_time_zero = iround(result_d[0]{0});
// Configure_Spectrometer_proc_fm(band,integ_time_zero,["wb1","wb1"],backend);
// //
// HIFI_Spectr_total_power_proc_fm(band,"wbs",integ_time_zero);
// //
// Hifi_HIFI_Single_cmd ($BBID, "HWH_ZERO_OFF");
// Hifi_HIFI_Single_cmd ($BBID, "HWV_ZERO_OFF");
// delay (1) ;
// //
// }
//////////////////////////////////////
// WITH THE NEW RULES THIS SHOULD BE
// A BLOCK. HOWEVER THIS PROCEDURE SHOULD
// NOT BE USED AS DEFAULT SO I EXPECT IT
// DISAPPEARS SOON.
//////////////////////////////////////
// WBS comb, procedure
// This is a work-around for WBS_Comb, with controlable att.
// and no zero integration
// The integration time is read in a configuration file
procedure WBS_comb_fm_proc {
string band = "1a"; // HIFI band
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Set zero On
Hifi_HIFI_switch_zero_WBS_H($BBID,"ON");
Hifi_HIFI_switch_zero_WBS_V($BBID,"ON");
delay(1);
//We have to set attenuators to values different from max.
//Initial configuration
//H-Polarization
//
{double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s","hwh_att_band4_comb","hwh_att_band3_comb","hwh_att_band2_comb","hwh_att_band1_comb","hwh_att_in_comb"],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_comb","hwv_att_band3_comb","hwv_att_band2_comb","hwv_att_band1_comb","hwv_att_in_comb"],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
//
//Configure spectroscopy
result_d = ConfigurationReader("name_delays",["integ_time_comb"],band,0.0);
int integ_time_comb = iround(result_d[0]{0});
Configure_Spectrometer_proc_fm(band,integ_time_comb,["wb1","wb1"],"wbs");
//
Hifi_HIFI_Single_cmd($BBID,"HWH_COMB_ON");
Hifi_HIFI_Single_cmd($BBID,"HWV_COMB_ON");
delay(1);
//
HIFI_Spectr_total_power_proc_fm(band,"wbs",integ_time_comb);
//
Hifi_HIFI_Single_cmd($BBID,"HWH_COMB_OFF");
Hifi_HIFI_Single_cmd($BBID,"HWV_COMB_OFF");
delay(1);
Hifi_HIFI_switch_zero_WBS_H($BBID,"OFF");
Hifi_HIFI_switch_zero_WBS_V($BBID,"OFF");
delay(1);
//
//Set attenuators back to default
WBS_config_block_fm(band);
}
//HIFI LO tuning only for M1/M2 investigation in 3b, block
//Target current is read from look-up table
block LO_tuning_w_M1M2M3_block_fm HIFI 3919 {
string band = "3b" in ["3b","3b"]; // HIFI band
double lo_freq = 930.0; //LO frequency
double m1 = 10.0; //M1 multiplier voltage
double m2 = -8.0; //M2 multiplier voltage
double m3 = 1.5; //M3 multiplier voltage
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Start_block();
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//
//Get target mixer current
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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],band,lo_freq);
double plevel_v = result[0]{0};
double m1_v = m1;
//result[1]{0};
double m2_v = m2;
//result[2]{0};
double m3_v = m3;
//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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = result[1]{1};
//
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};
//
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,lo_freq);
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 middle_d2 = result[0]{0};
double drain2_v_start = min(middle_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) * middle_d2;
//drain2_v_start;
step_drain2_v = (drain2_v_end - drain2_v_start) / double(nsteps - 1);
//
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
if(band == "3b") {
Hifi_HIFI_Conf_nom_LCU_ch3b($BBID,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);
//Send command: specific to M3 in 3b
delay(config_lo_delay);
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//
//
if(band == "3b") {
//Band 3b
Hifi_HIFI_Load_vector_nom_3b($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);
}
//
delay(1);
//
//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
HIFI_HL_store_tm_only_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
/////////////////////////////////////////////////////////////////
// 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 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;
}
// FSW Response time, procedure
procedure FSW_Response_time_proc_fm {
double hr_central_freq = 5.0; //IF freq of HRS hr sub-band in GHz
string hrs_polar = "H" in ["H","V","B"]; //HRS polarizations in use
int[] del_wbs_param = [10,200,10,100]; //starting, ending and step value for del_wbs
}{
//FSW will be called with increasing delta time between the two phases
//Need special spectroscopy configuration:
// - HRS only in hr resolution, optionally H, V or B, 1sec integration
HRS_config_resol_block_fm("0",["hr","hr"]);
FSW_Response_time_HRSConfig_block_fm("0",["hr","hr"],hr_central_freq);
//Optimize HRS level
HRS_tune_block_fm("0");
//Now call FSW at successive del_wbs
FSW_Response_time_block_fm(hrs_polar,del_wbs_param);
//
}
// Read addresses and get checksum for a given band
// Returns:
// - the array of address_start, address_length
// - the full checksum of a given band
// - the full length of all concatenated address areas
//
{{int,int}[],int,int} procedure LcuGetTableAddress_ops {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
string tab = "LcuAddressTable_R.config";
int bandnb = ilookup(tab,band,"bnum");
{int,int}[] pairs = [];
int total_length = 0;
int total = 12;
//Get inputs for band 1a - loop on location types
for(int line = 1 .. total) {
string add_name_S = "a" + line + "S";
//Start address in Hex
string add_name_L = "a" + line + "L";
//Length in byte
int add_S_1a = ilookup(tab,"1a",add_name_S);
int add_L_1a = ilookup(tab,"1a",add_name_L);
int add_S_band = add_S_1a + (bandnb - 1) * add_L_1a;
int add_L_band = add_L_1a;
pairs[line - 1] = {add_S_band,add_L_band};
//Full length of all concatenated address areas
total_length = total_length + add_L_band;
}
//Complement with zeroes until getting to 48 pairs
int hifi_NStep = 48;
for(int line2 = total + 1 .. hifi_NStep) {
add_S_band = 0;
add_L_band = 0;
pairs[line2 - 1] = {add_S_band,add_L_band};
}
//Get checksum
int crc = ilookup(tab,band,"crc");
return {pairs,crc,total_length};
}
// Chopper scan, procedure (IF power as function of chopper position)
procedure Chopper_scan_proc {
string band = "1a"; // HIFI band //Setting file
double chopper_pos_min = -7.0; //minimum chopper position
double chopper_pos_max = 8.0; //maximum chopper position
int n_steps = 300; //number of steps
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3
string shutter = "open"; //Status of shutter during scan: closed/open
int integ_time = 4; //Total integration time in sec.: at least 2sec !
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string chopmode = "tp" in ["tp","slowchop","fastchop"]; //modulation mode between hot/cold: tp, slowchop, fastchop
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length
bool ref_position = false; //Do we take a reference spectrum every 100sec ?
bool shutter_used = true;
}{
double chop = 0.0;
//
//close shutter if necessary
if(shutter_used) {
//Shutter_rotate_proc_fm("closed");
}
//
//Prepare for backend attenuation on hottest spot
if(shutter == "open") {
//External hot is available
Chopper_Rotation_block_fm(band,"chop_hot_ang","chop_M3_ang");
} else {
//Have to use internal hot
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_hot_ang");
}
//
//Configure and tune backends
//16/11/05: NOT ANYMORE, THIS SHOULD BE DONE INDEPENDENTLY
//HRS_config_block_fm(band,hrs_mode);
//WBS_config_block_fm(band);
//WBS calibration
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
WBS_tune_proc_fm(band);
}
if(backend == "hrs" || backend == "both") {
HRS_tune_block_fm(band);
}
//
//Configure spectrometers integration after tuning
int[] res = [0,0];
int n_wbs1 = 0;
int n_hrs_trans = 0;
int total_time = 0;
if(chopmode == "tp") {
res = Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
total_time = res[0] * res[1];
}
if(chopmode == "slowchop") {
res = Configure_Spectrometer_hc_slow_chop_proc_fm(band,integ_time * 2,hrs_mode,backend);
total_time = res[0] * res[1];
}
if(chopmode == "fastchop") {
//Integ_time expected here is the TOTAL integration time with both phases + residual HRS time
res = Configure_Spectrometer_fast_chop_proc_fm(band,integ_time * 2,chop_phase,hrs_mode,backend);
total_time = iceil(chop_phase * double(res[1] * res[2]));
n_wbs1 = res[2];
n_hrs_trans = res[3];
//debug_print("Fast chop parameters: n_wbs1 = "+res[2]+", n_hrs_trans = "+res[3]);
}
//
Chopper_scan_fm(band,chopper_pos_min,chopper_pos_max,n_steps,total_time,backend,chopmode,n_wbs1,n_hrs_trans,ref_position,shutter_used,hrs_mode,chop_phase);
//
//Configure spectrometers integration back to default in tp mode
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//We end with a spectrum on both external loads: Only for ILT !!
//They are needed in the analysis
//Hot_cold_external (band,total_time,backend); //integration on external loads: sky path
//
}
// Procedure to compute the LO settling delay for a particular frequency
//
int procedure LOSettlingTime {
string band = "4a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double rest_lofreq = 978.2; // LO frequency in GHz ! (David's units!)
bool usesVectorScan = false; // whether to make room for the vector scan
bool extradelay = true; //whether extra settling time is needed after chain is configured
}{
// check for needed overhead factor
if(usesVectorScan) {
double tune_range_factor = 1.05;
} else {
tune_range_factor = 1.0;
}
// Get all parameters needed to compute config_lo_delay in Configure_LCU
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";
}
//
// 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);
{double,string}[] result = ConfigurationReader(name_configlcutune,["drain2_v"],band,rest_lofreq / maxredshift);
double drain2_lowredshift = min(result[0]{0} * tune_range_factor,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} * tune_range_factor,drain2_bluemax_highredshift);
//
// Safe value
// (LO frequency must be in GHz here in contrast to other cal files.)
double[] cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,rest_lofreq);
double drain2_safe = cresult[0];
//
// 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});
//
//Add extra time if needed
if(extradelay) {
cresult = CalibrationReader("tunetime",["extra_tune_delay"],band,rest_lofreq);
config_lo_delay = config_lo_delay + iceil(cresult[0]);
}
// return result
return config_lo_delay;
}
//Set LOU to dissipative, block
block Set_LO_Dissipative_block_aot HIFI 6627 {
}{
mois_step("Switch to dissipative mode");
{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_dissipative($BBID);
delay(set_to_nominal_delay);
//
}
//////////////////////////////////////
// low-level procedures
//////////////////////////////////////
string procedure GetLcuSection {
}{
{double,string}[] result_d = ConfigurationReader("name_chopper",["prime_or_redundant"],"0",0.0);
string section = "P";
if(result_d[0]{1} == "redundant") {
section = "R";
}
return section;
}
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);
// 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;
}
bool isOffAtPoint = false;
////////////////////////////////////////////////////////////////////////
// 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;
iphase = iphase + 1;
}
//////////////////////////////////////////////////////////////////////
// States for actual observations
if(state[0] == 3) {
// First nodding position
// Check whether we are in a cross mode using computed OFF
isOffAtPoint = iscross && inod % 2 == 0;
// Configure measurement
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) {
if(isOffAtPoint) {
HIFIFastHalfChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates);
} else {
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
if(isOffAtPoint) {
HIFIFastHalfChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates);
} else {
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(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},load_datatime,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
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(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},load_datatime,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},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}};
}
// LCU3a configuration into SAFE mode, procedure
procedure LCU3a_config_safe_proc_fm {
string band = "3a"; // HIFI band
double lo_freq = 810.0 in [807.0,848.0]; //LO frequency
}{
error("This module is obsolete: use LCU_config_nominal_proc_fm instead");
}
/////////////////////////////
//Transition mode from normal to dissipative1
procedure HifiSetIntoDissipative_I_mois {
}{
//Clear potential failure mode
Set_LO_Nominal_block_aot();
//
LCU_switch_off_block_aot();
//Will put heaters to 6V
Set_LO_Dissipative_block_aot();
mois_spacon("Check that HL_MODE_S is set to dissipative");
//
//FPU stand-by: HBB is ON, chopper to rest position
Init_MSA_aot("0","CLOSE",0.0,true,"ON");
//HRS stand-by
HRS_config_max_att_block_aot("0",["wb","wb"]);
//WBS stand-by with laser OFF
WBS_standby_block_aot("OFF");
}
//////////////////////////////////////////////////////////////////////
// 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
double avgainfac = 0.5 / gssb[0] + 0.5 / gssb[1];
double rescalefac = sqrt(double(nfreq)) * avgainfac;
if(dsb) {
// Combine both sidebands
// In full spectral scans we have only a combined noise temperature for
// both sidebands
double decnoise_lores = dsbnoise_lores / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]);
double decnoise_hires = dsbnoise_hires / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]);
double indnoise_lores = dsbnoise_lores * rescalefac;
double indnoise_hires = dsbnoise_hires * rescalefac;
} else {
// Get single sideband noise equivalent
decnoise_lores = dsbnoise_lores * avgainfac;
decnoise_hires = dsbnoise_hires * avgainfac;
indnoise_lores = dsbnoise_lores * rescalefac;
indnoise_hires = dsbnoise_hires * rescalefac;
}
// In spectral scans we have only a combined noise temperature for both
// sidebands, so that the USB/LSB separation is not used
return {decnoise_lores,decnoise_hires,indnoise_lores,indnoise_hires,noiseratio};
}
// 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;
}
// LCU5b configuration into SAFE mode, procedure
procedure LCU5b_config_safe_proc_fm {
string band = "5b"; // HIFI band
double lo_freq = 1200.0 in [1192.0,1242.0]; //LO frequency
}{
error("This module is obsolete: use LCU_config_nominal_proc_fm instead");
}
//backend attenuation during peakup in IST context, procedure
procedure Peakup_backend_attenuation_proc_fm {
string band = "1" in ["1","2","3","4","5","6","7"]; // HIFI band
int position = 1 in [1,9]; //peakup pattern sequence number: from 1 to 9
string peakup_matrix = "centred" in ["centred","offseted","flat"]; //Which brightness distribution to simulate with shutter
string backend = "hrs" in ["hrs","wbs"]; //Backend in use: hrs or wbs
int total_time = 2; //Total integration time in sec.
}{
//Get number of shutter rotation steps depending on position number
string band_nb = band + "a";
string name_shutter_pos = "name_shutter_pos_centred";
if(peakup_matrix == "offseted") {
name_shutter_pos = "name_shutter_pos_offseted";
}
{double,string}[] result = ConfigurationReader(name_shutter_pos,["new_att"],band_nb,double(position));
//If flat distribution is chosen, the attenuators shall not be changed
double new_att = result[0]{0};
if(peakup_matrix == "flat") {
new_att = 10.0;
}
//
//Apply new attenuation
if(backend == "hrs") {
HRS_config_att_lo_w_att_fm(band_nb,["wb1","wb1"],new_att);
} else {
new_att = new_att + 5.0;
//for WBS we move the main att, all others to 7
int[] att_h = [7,7,7,7,iround(new_att)];
int[] att_v = [7,7,7,7,iround(new_att)];
//Presently assumes use of laser2
WBS_config_w_laser_and_att_proc_fm(band_nb,"Laser2","Laser2",att_h,att_v,total_time,backend);
}
//
}
//HIFI-COP-3-Deflux
//Systematic deflux at beginning of each OD, or band switch
procedure Deflux_SingleBand_proc_ops {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b"]; // HIFI band. ALL does all mixer bands
}{
// Get reference frequency
string keyfreqname = "keyfreq";
//this is for cold LO operations
// "keyfreq" for cold LO operations
// "keyfreq_dummy" for dummy LO operations
double[] result_d = CalibrationReader("name_keyfreq",[keyfreqname],band,0.0);
double lo_freq = result_d[0];
//
//Switch on LO
LCU_switchon_proc_fm(band);
//Wait 1 min from now
sync();
int startobs = time();
//Insert FPU setting at this frequency
Init_MSA_HBB_fm(band,"CLOSE",lo_freq,"ON");
delay(60 - (time() - startobs));
//Tune LO
LO_tuning_block_fm(band,lo_freq);
//First magnet tuning
Magnet_tuning_block_fm(band,lo_freq,"HRS",40);
//Deflux heaters
Heater_cop(band);
//Second magnet tuning
Magnet_tuning_block_fm(band,lo_freq,"HRS",40);
//Third magnet tuning
Magnet_tuning_block_fm(band,lo_freq,"HRS",40);
}
// 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
// For FSW measurements a full preamble of 2xLCU_Configure is needed
// as for a new setting (not fully confirmed yet, but safe solution !)
HIFITuneFreqFsw(band,tuning_freq,tuning_freq + freq_throw,true,"");
danglingreadout = HIFI_DoubleCalibrate_hot_cold(band,lo_freq,used_datatime,n_inttime,backendreadoutparms,false);
}
}
//Find out stepmargin
double procedure Stepmargin {
double low = 0.0;
double high = 10.0;
string parameter = "hifi_HIF_mx_mg_step_C";
}{
double range = high - low;
int range_raw = convert_to_raw(parameter,range);
if(range_raw < 1) {
range_raw = 1;
}
double bitsize = range / double(range_raw);
return bitsize / 4.0;
}
//Full memory dump of the LCU
mode HifiManCmd_LCU_Full_Memory_Dump {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to dump the full LCU memory");
StartMode_block_ops();
//
mois_spacon("Check that HL_MODE_S is set to standby1 or standby0");
//
mois_step("Copy safe tables");
LCU_DEF_SAFE_block_mois();
//
mois_step("Dump full LCU memory");
int start_address = 0;
// start page in XRAM
int npages = 0x80;
//number of pages to dump: Use 0x80 for full area
LCU_Full_Memory_Dump_block_mois(start_address,npages);
//
StopMode_block_mois();
}
// 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]);
}
// procedure called to get the WBS lasers switched on
procedure HifiSetFromDissipative_I_IntoDissipative_II {
string band_dissipate = "4a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//Temporarily, HEBs cannot be used - needs new MIB
if(band_dissipate == "6a" || band_dissipate == "6b" || band_dissipate == "7a" || band_dissipate == "7b") {
//error("HEB bands cannot yet be used in dissipative mode");
}
//
//WBS stand-by with laser ON
WBS_standby_block_aot("ON");
//Warm-up LOU with next band to be used
if(band_dissipate == "0") {
//Do nothing as one should already be in band0
} else {
//Clear potential failure mode
Set_LO_Nominal_block_aot();
//Heater will remain at 4V
LCU_config_dissipative_w_D2_proc_aot(band_dissipate);
}
//
}
/////////////////////////////////////////////////////////////////
// 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 Single Point - DBS fastChop",{data_time,0,n_switch_on,n_int_on,0,0,0,0,n_cycles,load_interval});
ChopMessages(true,data_time,n_int_on);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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 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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
// Spectrometer configuration for slow chop, low level procedure
// Specific for hotcold or chopper calib cases (longer del_wbs)
int[] procedure Configure_Spectrometer_hc_slow_chop_proc_fm {
string band = "1a"; // HIFI band
int integ_time = 8; //Total integration time in sec. for the two phases !
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,wb5
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//First derive backend setting codes as expected by VO's routine
//Build up backend parameter tupple:
{{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = BackendSettings(band,0.0,hrs_mode,backend);
// Readout parameters for HRS1,HRS2, WBS1,WBS2
//Compute data_time and n_switch use the wrapper
int[] res = ConfigSlowChop(integ_time,"chopcal",band,0.0,backendreadoutparms);
int data_time = res[0];
int n_switch = res[1];
// Now call the spectroscopy setup: it is common to ILT and AOT CUS.
// The deadtimes output is not used at ILT level.
{double,double} dtimes = ConfigSpectroscopySlowChop_IST(data_time,n_switch,"chopcal",band,0.0,backendreadoutparms,true);
//
return res;
}
//
//Set LOU to nominal, block
//Set LOU in nominal mode with no
//channel selected
block Set_LO_Nominal_block_fm HIFI 3626 {
}{
//
//Start_block();
{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);
//
}
// FPU Standby with chopper switched on. HBB is also ON per default, block
block Band0_chopper_on_fm HIFI 3297 {
string band = "0"; // HIFI band
string chop_loop = "CLOSE"; // Chopper Loop status
}{
Start_block();
//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,0.0);
int band_nb = iround(result_d[0]{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,0.0);
//
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";
result_d = ConfigurationReader("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2","chop_g3","chop_p3","calibrator_current"],band,0.0);
//
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};
//
result_d = ConfigurationReader("name_confilfpu",["bias_standby_h","diplexer_standby_h","bias_standby_v","diplexer_standby_v","diplex_h_ctrl_mode","diplex_v_ctrl_mode","chop_M3right"],band,0.0);
//
double bias_H = result_d[0]{0};
double diplex_H = result_d[1]{0};
double bias_V = result_d[2]{0};
double diplex_V = result_d[3]{0};
int diplex_h_ctrl_mode = iround(result_d[4]{0});
int diplex_v_ctrl_mode = iround(result_d[5]{0});
//
//Retrieve magnets Magnet are so far at maximum value. Now set to nominal
double magnetcurrent_H = result_d[1]{0};
double magnetcurrent_V = result_d[4]{0};
//
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
result_d = ConfigurationReader("name_confilfpu",["magnet_standby_h","magnet_standby_v"],band,0.0);
magnetcurrent_H = result_d[0]{0};
magnetcurrent_V = result_d[1]{0};
}
//
result_d = ConfigurationReader("name_chopper",["chop_startup_cold"],band,0.0);
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.
//chopper = Check_Chopper_Prime_Redundant(chopper);
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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,0.0);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
}
////////////////////////////////////
// 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 Map slowChop",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval});
ChopMessages(false,data_time,n_switch_on);
RasterSizeMessages({0.0,0.0},stepsize,2,npoints,true);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
//Transition mode to standby1
procedure HifiSetIntoStandby_I_proc_mois {
}{
//Go to standby1
mois_step("Go to standby1 mode");
LCU_standby1_block_mois();
//
//Heater switch no longer embedded in this procedure
//Should be called with another procedure (HifiManCmd_Set_HL_Heater)
//
}
////////////////////////////////////
// Blocks
////////////////////////////////////
// Simulating PU report packet emission
block Simulate_PU_block_ops HIFI 7822 {
}{
StartBlock_ops();
mois_step("Send simulated micro-rotations to ACMS");
int hifi_HI_microrot_y = 5;
// HI_microrot_y
int hifi_HI_microrot_z = 7;
// HI_microrot_z
Hifi_HIFI_simulate_peakup(hifi_HI_microrot_y,hifi_HI_microrot_z);
delay(1);
}
//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_standby1_block_mois HIFI 3730 {
}{
{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);
}
////////////////////////////////////////////////////////////////////////////
// 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
int tline = telescopetimes[4];
// Time in line
// The telescope slew can be a bit further than requested
int line_inttime = 2 * n_perline * data_time;
{int,int} otfline = OtfTelescopeLine(line_inttime,tline);
int line_startdelay = otfline{1};
////////////////////////////////////////////////////////////////////////
// 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
delay(line_startdelay);
// 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();
}
}
}
//Transition mode from normal to dissipative2
procedure HifiSetFromNormal_IntoDissipative_II {
string band_dissipate = "4a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//Temporarily, HEBs cannot be used - needs new MIB
if(band_dissipate == "6a" || band_dissipate == "6b" || band_dissipate == "7a" || band_dissipate == "7b") {
//error("HEB bands cannot yet be used in dissipative mode");
}
//
if(band_dissipate == "0") {
//Clear potential failure mode
Set_LO_Nominal_block_aot();
//
LCU_switch_off_block_aot();
//Will put heaters to 6V
Set_LO_Dissipative_block_aot();
} else {
//Clear potential failure mode
Set_LO_Nominal_block_aot();
//Heater will remain at 4V
LCU_config_dissipative_w_D2_proc_aot(band_dissipate);
}
//
//FPU stand-by: HBB is ON, chopper to rest position
Init_MSA_aot("0","CLOSE",0.0,true,"ON");
//HRS stand-by
HRS_config_max_att_block_aot("0",["wb","wb"]);
//WBS stand-by with laser ON
WBS_standby_block_aot("ON");
//Enable checksum computation - moved to transition to diss1 (HIFI-3578)
//Enable_CRC_FDIR_block_ops();
}
//Set LCU6Ha back to standby status, procedure
procedure LCU6Ha_standby_proc_fm {
string band = "7a"; // HIFI band
double lo_freq = 1700.0 in [1700.0,1800.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
//HIFI-COP-2.3-Param-Scan block0: TPF maker
procedure TPF_maker_paramscan {
int index = 1 in [1,2]; // Test case index as of config_paramscan_COP.config
}{
//Read all band+param to perform
string tab = "config_paramscan_COP.config";
int total = table_size(tab);
string band = slookup(tab,"" + index,"band");
//
//Switch-on LO
//We use a constant frequency for each band, regardless of the input
double lo_freq = 0.0;
double[] result_d = CalibrationReader("name_keyfreq",["keyfreq","midfreq","keyfreqwarm","keyfreq_dummy"],band,0.0);
lo_freq = result_d[0];
//this is for cold operations
//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";
string name_configlotune = "name_configlotune_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";
name_configlotune = "name_configlotune_b";
}
//
{double,string}[] result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = 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});
//
cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lo_freq);
drain2_v = cresult[0];
//
//Generate TPF parameters
//Convert into raw:
int g1 = convert_to_raw("hifi_HL_Gate1_7B_V",gate1_v);
int g2 = convert_to_raw("hifi_HL_Gate2_7B_V",gate2_v);
int vd1 = convert_to_raw("hifi_HL_Drain1_7B_V",drain1_v);
//convert_to_raw does not work for params defined through TextualCalibrationCurves
//The convertion is:
if(curlim1 == "1.5") {
int curl1 = 0;
}
if(curlim1 == "1.4") {
curl1 = 2;
}
if(curlim1 == "1.3") {
curl1 = 1;
}
if(curlim1 == "1.22") {
curl1 = 3;
}
//
if(curlim2 == "1.5") {
int curl2 = 0;
}
if(curlim2 == "1.4") {
curl2 = 2;
}
if(curlim2 == "1.3") {
curl2 = 1;
}
if(curlim2 == "1.22") {
curl2 = 3;
}
int vd2 = convert_to_raw("hifi_HL_Drain2_7B_V",drain2_v);
int mm1 = convert_to_raw("hifi_HL_M1_7B_V",m1_v);
int mm2 = convert_to_raw("hifi_HL_M2_7B_V",m2_v);
Hifi_HIFI_WBS_Zero(mm1);
Hifi_HIFI_WBS_Zero(mm2);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
message("" + m1_v);
message("" + m2_v);
message("" + gate1_v);
message("" + gate2_v);
message("" + drain1_v);
message("" + curlim1);
message("" + drain2_v);
message("" + curlim2);
//
//Parameters from LO_tuning_w_M1M2_block_fm(band,lo_freq,m1,m2)
//Read all band+param to perform
lo_freq = dlookup(tab,"" + index,"lofreq");
cresult = CalibrationReader("name_lcu_safe_values",["g1_v","g2_v","d1_v","d2_v"],band,lo_freq);
gate1_v = cresult[0];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
result = ConfigurationReader(name_configlcu,["gate1_v"],band,lo_freq);
gate1_v = result[0]{0};
}
//
gate2_v = cresult[1];
drain1_v = cresult[2];
drain2_v = cresult[3];
//
result = ConfigurationReader(name_confindex,["freq_nx"],band,lo_freq);
freq_nx = ifloor(result[0]{0});
//Compute lsu_main and offset
resu = ComputeLSU_A_M_R(band,lo_freq);
lsu_main = resu[0];
lsu_offset = resu[1];
//Get checksum
result = ConfigurationReader("name_delays",["cus_checksum"],band,lo_freq);
macro_checksum = iround(result[0]{0});
//
result = ConfigurationReader(name_configlo,["curlim1_v","curlim2_v"],band,lo_freq);
curlim1 = result[0]{1};
curlim2 = result[1]{1};
//
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};
//
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;
//
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);
//The automatic tuning shall use the min of the nominal best-guess and Vd2max - 100mV
double middle_d2 = min(result[0]{0},drain2_bluemax - 0.1);
double drain2_v_start = min(middle_d2 * (1.0 + tune_range / 2.0),drain2_bluemax);
//Convert into raw:
g1 = convert_to_raw("hifi_HL_Gate1_7B_V",gate1_v);
g2 = convert_to_raw("hifi_HL_Gate2_7B_V",gate2_v);
vd1 = convert_to_raw("hifi_HL_Drain1_7B_V",drain1_v);
//convert_to_raw does not work for params defined through TextualCalibrationCurves
//The convertion is:
if(curlim1 == "1.5") {
curl1 = 0;
}
if(curlim1 == "1.4") {
curl1 = 2;
}
if(curlim1 == "1.3") {
curl1 = 1;
}
if(curlim1 == "1.22") {
curl1 = 3;
}
//
if(curlim2 == "1.5") {
curl2 = 0;
}
if(curlim2 == "1.4") {
curl2 = 2;
}
if(curlim2 == "1.3") {
curl2 = 1;
}
if(curlim2 == "1.22") {
curl2 = 3;
}
vd2 = convert_to_raw("hifi_HL_Drain2_7B_V",drain2_v_start);
//Read all band+param to perform
double m1_min = dlookup(tab,"" + index,"m1_1");
double m1_max = dlookup(tab,"" + index,"m1_2");
double m1_step = dlookup(tab,"" + index,"m1_step");
double m2_min = dlookup(tab,"" + index,"m2_1");
double m2_max = dlookup(tab,"" + index,"m2_2");
double m2_step = dlookup(tab,"" + index,"m2_step");
double bias_min = dlookup(tab,"" + index,"bias_1");
double bias_max = dlookup(tab,"" + index,"bias_2");
double bias_step = dlookup(tab,"" + index,"bias_step");
double imix_min = dlookup(tab,"" + index,"imix_1");
double imix_max = dlookup(tab,"" + index,"imix_2");
double imix_step = dlookup(tab,"" + index,"imix_step");
double m1 = 0.0;
double m2 = 0.0;
//Phase 1 measurement: loop on M1 and M2
m1 = m1_max;
//Loop on M1
double margin = 1.0E-7;
while(m1 >= m1_min - margin) {
//Loop on m2: cancelled for the moment - SCR-2460
m2 = m2_max;
//while (m2>=m2_min) {
//
mm1 = convert_to_raw("hifi_HL_M1_7B_V",m1);
mm2 = convert_to_raw("hifi_HL_M2_7B_V",m2);
//Implementation of SCR-2460: for the time being, M2 is fixed to its nominal value - no scan
result = ConfigurationReader(name_configlcu,["m2_v"],band,lo_freq);
m2 = result[0]{0};
mm2 = convert_to_raw("hifi_HL_M2_7B_V",m2);
//
//Values for pre-amble
Hifi_HIFI_WBS_Zero(mm1);
Hifi_HIFI_WBS_Zero(mm2);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
message("" + m1);
message("" + m2);
message("" + gate1_v);
message("" + gate2_v);
message("" + drain1_v);
message("" + curlim1);
message("" + drain2_v_start);
message("" + curlim2);
//Values for vector scan
Hifi_HIFI_WBS_Zero(mm1);
Hifi_HIFI_WBS_Zero(mm2);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//
//message(band+", "+lo_freq+", "+m1+", "+m2);
message("" + m1);
message("" + m2);
message("" + gate1_v);
message("" + gate2_v);
message("" + drain1_v);
message("" + curlim1);
message("" + drain2_v_start);
message("" + curlim2);
//
//m2 = m2+m2_step;
//} //end loop m2
m1 = m1 + m1_step;
}
//end loop m1
}
//LO parameter scan without HotCold measurement
//for Band 1a
procedure LCU1a_power_scan_without_Tsys {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4
double lo_freq = 500.0 in [488.0,552.0]; //LO frequency
double param_min = 1.0; //Min. of scanned parameter
double param_max = 2.0; //Max. of scanned parameter
double step_size = 0.1; //Step size
string param_name = "D2"; //Code of scanned parameter: M1,M2,G1,G2,D1,D2.
}{
error("This module is obsolete: use LCU_power_scan_without_Tsys instead");
}
// LO settling time for a LO sub-band change, procedure.
// Measures series of spectra while switching from
// one sub-band to another
procedure LO_Settling_time_proc_fm {
string band_a = "1a" in ["1a","2a","3a","4a","5a","6a","7a"]; // HIFI band a
string band_b = "1b" in ["1b","2b","3b","4b","5b","6b","7b"]; // HIFI band a
int int_time1 = 3600; //Integration time after first tuning
int int_time2 = 600; //Integration time after first and second switch
double lo_freq_a = 500.0; //LO frequency in sub-band a
double lo_freq_b = 600.0; //LO frequency in sub-band b
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//
//Get cold position
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["chop_cold"],band_a,0.0);
double chop = result_d[0]{0};
//
//WBS calibration
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band_a);
}
//Set up mixer for lo_freq_a
Init_MSA_fm(band_a,"CLOSE",lo_freq_a,"ON");
LO_Settling_time_first_tuning_fm(band_a,int_time1,lo_freq_a,backend);
//
Init_MSA_fm(band_b,"CLOSE",lo_freq_b,"ON");
LO_Settling_time_second_tuning_fm(band_b,int_time2,lo_freq_b,backend);
//
Init_MSA_fm(band_a,"CLOSE",lo_freq_a,"ON");
LO_Settling_time_third_tuning_fm(band_a,int_time2,lo_freq_a,backend);
//
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Map Frequency Switch noRef",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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 frame transmission time (always 2 spectra)
int data_time = wbs_comb_delay / 2;
int rest_delay = wbs_comb_delay - 2 * data_time;
wbs_comb_delay = wbs_comb_delay - rest_delay;
// 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 = AllDataRates(fullreadoutparms,data_time,false);
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);
// Insert a Noop because previous command could have been issued in second bus slot
Hifi_HIFI_noop();
// 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);
delay(rest_delay);
//
// additional delay for packet transmission before next zero depends
// on zero duration - needs to be introduced on higher level
return readout;
}
// HRS partial configuration, procedure
// Configures the LO and attenuators
procedure HRS_config_att_lo_fm {
string band = "1a"; // HIFI band
string[] hrs_mode = ["mr","mr"]; //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_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 = [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_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 = [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 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);
}
// Functional test with pumped mixer, procedure
procedure FT_pumped {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,etc
int integ_time = 4; //Integration time
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
double lo_freq = 500.0; //LO frequency
}{
//
//WBS calibration. Attenuators are set later in the magnet tuning
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_config_block_fm(band);
WBS_calib_fm(band);
}
if(backend == "hrs" || backend == "both") {
HRS_config_block_fm(band,hrs_mode);
}
//
//Re-Configure spectrometer integration
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
IVcurve_pumped_fm(band,lo_freq);
//
//Does a magnet tuning: only up to band 5 since band6-7 have no magnets
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
Magnet_tuning_block_fm(band,lo_freq,"HRS",40);
}
//
//Go on hot load
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_hot_ang");
//Tune backends on the hot load
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_tune_proc_fm(band);
}
if(backend == "hrs" || backend == "both") {
HRS_tune_block_fm(band);
}
//Reconfigure spectrometer integration after tuning
int[] res = Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//Radiometry on internal loads
Hot_cold(band,hrs_mode,backend,res[0] * res[1],"tp",0,0);
//Back to middle of M3
Chopper_Rotation_block_fm(band,"chop_hot_ang","chop_M3_ang");
}
/////////////////////////////////////////////////////////////////
// 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;
}
// Initialisation, block with all IF set ON but unpumped mixers
block Init_all_IF_fm HIFI 3215 {
string band = "1a"; // HIFI band
string mixer_polarization = "B" in ["H","V","B"]; //Polarization: H, V, or both (B)
}{
Start_block();
//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,0.0);
int band_nb = iround(result_d[0]{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};
// Check whether H-polar is requested
if(mixer_polarization == "V") {
result_d = ConfigurationReaderWarm("name_confilfpu",["fif1v_h","fif1c_h","fif2v_h","fif2c_h","sif1v_h","sif1c_h","sif2v_h","sif2c_h","sif3v_h","sif3c_h"],"0",0.0);
//
volt_H_FIF_1 = result_d[0]{0};
curr_H_FIF_1 = result_d[1]{0};
volt_H_FIF_2 = result_d[2]{0};
curr_H_FIF_2 = result_d[3]{0};
//
volt_H_SIF_1 = result_d[4]{0};
curr_H_SIF_1 = result_d[5]{0};
volt_H_SIF_2 = result_d[6]{0};
curr_H_SIF_2 = result_d[7]{0};
volt_H_SIF_3 = result_d[8]{0};
curr_H_SIF_3 = result_d[9]{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,0.0);
//
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};
// Check whether H-polar is requested
if(mixer_polarization == "H") {
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"],"0",0.0);
//
volt_V_FIF_1 = result_d[0]{0};
curr_V_FIF_1 = result_d[1]{0};
volt_V_FIF_2 = result_d[2]{0};
curr_V_FIF_2 = result_d[3]{0};
//
volt_V_SIF_1 = result_d[4]{0};
curr_V_SIF_1 = result_d[5]{0};
volt_V_SIF_2 = result_d[6]{0};
curr_V_SIF_2 = result_d[7]{0};
volt_V_SIF_3 = result_d[8]{0};
curr_V_SIF_3 = result_d[9]{0};
}
//
string chop_sine_s = "ON";
string chop_loop = "CLOSE";
//Chopper is not used anyway
result_d = ConfigurationReader("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2","chop_g3","chop_p3","calibrator_current_on"],band,0.0);
//
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};
//
//Junctions do not need to be biased, nor should diplexers be moved
double bias_H = 0.5;
double magnetcurrent_H = 0.0;
double bias_V = 0.5;
double magnetcurrent_V = 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 chopper = 0.0;
//
//
chopper = Check_Chopper_Prime_Redundant(chopper);
HIFI_Configure_FCU_proc_fm(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,0.0);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
}
////////////////////////////////////
// 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};
}
//HIFI-COP-2.1-DPL-RespTime
//Check diplexer response time for all diplexer bands
obs HifiEng_Diplexer_Response_time_COP {
string band = "3a" in ["3a","4a","6a","7a"]; //Mixer diplexer band: 3a, 4a, 6a or 7a
string mixer_polarization = "H"; //mixer polarization: H or V
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Diplexer_Response_time_COP_proc_ops(band,mixer_polarization));
// 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) {
// Test execution
Diplexer_Response_time_COP_proc_ops(band,mixer_polarization);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
////////////////////////////////////
// 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 Map Position Switch",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
//HIFI LO tuning and vector scan, block
block LO_tuning_Vecscan_block_fm HIFI 3690 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Prepare for tuning
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//
//Get target mixer current
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});
}
//
//Start_block();
//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";
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";
}
//
result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V: goes to -0.91 manually for test only
if(band == "6b") {
gate1_v = result[5]{0};
//Use 0.91V between 1613 and 1660 GHz
if(lo_freq >= 1613.0 && lo_freq <= 1660.0) {
gate1_v = -0.91;
}
}
//
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});
//
cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lo_freq);
double drain2_safe = cresult[0];
drain2_v_start = drain2_safe;
//
double drain2_max = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq);
//
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;
//
//For bands 1 to 5, scan will be done with increasing drain2 voltages
//
//For bands 6 to 7, scan will be done with decreasing drain2 voltages: NOT FOR THIS TEST !!
if(band == "6a" || band == "7a" || band == "6b" || band == "7b") {
//step_drain2_v = -1.0*step_drain2_v;
//drain2_v_start = drain2_max;
//Also, it probably makes no sense to go down to the safe value
drain2_v_start = drain2_safe + 0.45;
//i.e. go to 1.7
//Need to check that drain2_v_start has not got above the blue max
//If so, the range to scan is not so big so we stick to the safe value
//as minimum drain2 for the scan
if(drain2_v_start >= drain2_max) {
drain2_v_start = drain2_safe;
}
}
//
result = ConfigurationReader(name_configlotune,["nsteps","step_time"],band,lo_freq);
int nsteps = iround(result[0]{0});
double step_drain2_v = -1.0 * (drain2_max - drain2_v_start) / double(nsteps - 1);
drain2_v_start = drain2_max;
double step_time = 5.0;
//result[1]{0};
//
//Preliminary configuration at high Vd2
//
//Compute config_lo_delay: new approach: use ramp-up time
result = ConfigurationReader("name_delays",["lock_lo_delay","vd2_rampup_speed"],band,lo_freq);
int config_lo_delay = iceil(result[0]{0} + (drain2_v_start - drain2_safe) / result[1]{0});
//Old approach: fixed delay
//result = ConfigurationReader("name_delays",
// ["config_lo_delay"],band, lo_freq);
//int config_lo_delay = iround(result[0]{0});
//
//Send command
HIFI_Configure_LCU_proc_fm(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);
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "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_nom_3b($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 == "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);
}
//
//delay(1);
//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
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
// Procedure to support conditional LCU CRC computation
// together with standard HK configuration - HIFI-3415
procedure HIFILCUChecksumAndSetHKCloseObs {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
bool alltables = true; //check all tables+unused (true), or only one band table (false)
string speed = "normal" in ["fast","normal","slow"]; // Select HK rate
bool active = false; // Whether to actively query the spectrometers
}{
HIFISetHK(speed,active);
LcuChecksumRecalcCloseObs_aot(band,alltables);
}
//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);
}
//HIFI-COP-1.2-LO_FT
procedure COP_LO_FT_TPF_maker {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//
double[] cresult_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = cresult_d[0];
//applies to cold LO
//
//Get diplexer settings at this frequency
int diplh = convert_to_raw("hifi_HF_CH1_DPACT_C",0.0);
int diplv = convert_to_raw("hifi_HF_CV1_DPACT_C",0.0);
if(band == "3a" || band == "3b" || band == "4a" || band == "4b" || band == "6a" || band == "6b" || band == "7a" || band == "7b") {
double[] result_dip = Get_Diplexer_setting(band,lo_freq);
diplh = convert_to_raw("hifi_HF_CH1_DPACT_C",result_dip[0]);
diplv = convert_to_raw("hifi_HF_CV1_DPACT_C",result_dip[1]);
}
Hifi_HIFI_WBS_Zero(diplh);
Hifi_HIFI_WBS_Zero(diplv);
//Switch on with safe Vd2
//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","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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};
//
cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lo_freq);
drain2_v = cresult[0];
//Note: check that Vd2 is within the blue limits
drain2_v = Check_BLUE_LIMIT_D2_proc_fm(band,lo_freq,drain2_v);
//Send command: expect that we have already switched to NOMINAL
//We set D2 to best guess and wait some time to stabilize chain temperature
int bbid = 237043713;
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);
}
//
//Set heater to their switch-on value
bbid = 236912641;
string context = "nominal";
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);
//LO_SFT_proc_cop
//Send command: expect that we have already switched to NOMINAL
//We set D2 to best guess and wait some time to stabilize chain temperature
bbid = 237043714;
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);
}
//
//Set heater to their switch-on value
bbid = 236912642;
context = "nominal";
cresult = CalibrationReader("name_loheater",["heater_nominal","heater_stby"],band,0.0);
hifi_HL_heater = cresult[0];
if(context == "stby") {
hifi_HL_heater = cresult[1];
}
Hifi_HIFI_HL_heater(bbid,hifi_HL_heater);
//Send best-guess Vd2 for SFT
cresult_d = CalibrationReader("name_keyfreq",["key_d2v_P","key_d2v_R"],band,0.0);
//Check what d2_v to use depending on test circumstances
drain2_v = cresult_d[0];
//Value for prime case, and fm H/W
if(prime_or_redundant == "redundant") {
drain2_v = cresult_d[1];
}
//
//Note: check that Vd2 is within the blue limits
drain2_v = Check_BLUE_LIMIT_D2_proc_fm(band,lo_freq,drain2_v);
bbid = 237043715;
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);
}
//
}
//////////////////////////////////////////////////////////////////////////
// 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);
// tss not relevant for ncycles=1, scansize=1
if(scansize != 1 || n_cycles != 1) {
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(n_loadinterval > 1 && (dangling_period + n_loadinterval) * 2 * scan_time > load_interval - loadlength + nodtime) {
n_loadinterval = n_loadinterval - 1;
dangling_period = n_cycles % n_loadinterval;
}
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};
}
// Take slow chop spectra, block
block Spectro_slow_chop_block_fm HIFI 3607 {
string band = "1a"; // HIFI band
double[] chop_angle = [-1.0,+1.0]; //The two angles to chop between
int[] timing_parms = [4,2]; //single readout time in sec. and n_wbs_start
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
int integ_time = timing_parms[0] * timing_parms[1];
//Compute data-rate
double[] rates = ILT_datarate_proc_fm(band,backend,"slowchop",integ_time);
//Take spectrum
// set data rates
non_ess_hk_data_rate(rates[2] / 1024.0);
data_rate(rates[0] / 1024.0);
//
HIFI_Spectr_slow_chop_proc_fm(chop_angle[0],chop_angle[1]);
//This probably needs to be adapted
Apply_Slow_Chop_delay(integ_time,band,backend);
// reset data rates
non_ess_hk_data_rate(rates[1] / 1024.0);
data_rate(0.0);
}
// Switch HIFI off, mode
// Assumed to be in rescue mode when starting this mode
//
mode HifiManCmd_HIFI_Rescue_to_switched_off {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
Mode_status_check_rescue("failure");
mois_comment("Switch from HIFI rescue to switch off: switches off the ICU");
//Here ICU is not working properly so no obsid or HK handling
//StartMode_block_ops();
string icu_subsys = "ICU_Prime";
if(prime_or_redundant == "Red") {
icu_subsys = "ICU_Red";
}
PDU_switch_off_block_ops(icu_subsys);
//Here, HIFI is idle: the switch back to obsid = 0 is done just before ICU switched off
//StopMode_block_mois () ;
Mode_status_check_switched_off();
}
// LCU3b configuration and tuning, procedure
procedure LCU3b_config_tune_proc_fm {
string band = "3b"; // HIFI band
double lo_freq = 900.0 in [852.0,953.0]; //LO frequency
double drain_2_factor = 100.0; //Percentage factor of the targetted drain voltage
}{
error("This module is obsolete: use LO_tuning_block_fm instead");
}
//Simple setting of HL_Modes_S to dissipative
mode HifiManCmdSetIntoDissipative {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to set HL_Modes_S to dissipative");
StartMode_block_ops();
//
mois_step("Set HL_Modes_S to dissipative");
Set_LO_Dissipative_block_aot();
mois_spacon("Verify that HL_MODE_S is set to dissipative");
//
StopMode_block_mois();
}
// Stability test, procedure
// Measurement of internal cold in FSW mode
// In COP, look at the sky
procedure Proc_stability_freqswitch_COP {
string band = "1a"; // HIFI band
double lo_freq = 522.0; //The LO frequency
double freq_throw = 50.0; //The frequency throw in MHz
int n = 100; //Number of load pairs to be measured
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total (co-added) integration time of a phase in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
int freq_index = 1; //Frequency index to be applied
}{
//
//Tune to the two frequencies: the first frequency is the one
//used to tune the backends
//
//Set Diplexer to the frequency used for the standing wave test
//Implementation of SCR-2348
string tabstwv = "config_stwvfreq.config";
double bandnb = GetBandCode(band);
double stwvfreq = dlookup(tabstwv,"" + iceil(bandnb),"freq" + freq_index);
Set_Diplexer_current_FSW_block_fm(band,stwvfreq);
//Old approach: diplexer at middle freq between FSW1 and FSW2
//Set_Diplexer_current_FSW_block_fm(band,lo_freq+freq_throw/2000.);
//
//Set to FSW1
LO_tuning_FSW_block_fm(band,lo_freq,lo_freq + freq_throw / 2000.0,true);
//The frequency settings are automatically stored in register FSW1
//
//Configure backends
if(backend == "hrs" || backend == "both" || backend == "hrsFast") {
HRS_config_block_fm(band,hrs_mode);
HRS_tune_block_fm(band);
}
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
//WBS calibration
WBS_calib_fm(band);
WBS_tune_proc_fm(band);
}
//
//set to FSW2
LO_tuning_FSW_block_fm(band,lo_freq + freq_throw / 1000.0,lo_freq + freq_throw / 2000.0,false);
//The frequency settings are automatically stored in register FSW2
//
//Configure spectrometers integration after tuning: done later
//Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_M3_ang");
//Look at M3 for stability measurement
//
Stability_freqswitch_fm(band,n,integ_time,hrs_mode,backend);
//Configure spectrometers integration back to default in tp mode
Configure_Spectrometer_proc_fm(band,4,hrs_mode,backend);
//2 sec. integration
}
// Rotate angle by -90 deg
double procedure RotateRight {
double angle = 0.0; // Original angle
}{
double fullcircle = 360.0;
return (angle + fullcircle * 0.75) % fullcircle;
}
// WBS configuration with minimum attenuation, block
// Laser can be chosen
block WBS_config_min_att_w_laser_block_fm HIFI 3642 {
string band = "1a"; // HIFI band
string laser_H = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-V laser to be set ON
}{
//Start_block();
//H-Polarization
//
{double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s"],band,0.0);
string hwh_laser1_s = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
int hwh_heater = iround(result_d[2]{0});
string hwh_latchup_s = result_d[3]{1};
int hwh_att_band4 = 0;
int hwh_att_band3 = 0;
int hwh_att_band2 = 0;
int hwh_att_band1 = 0;
int hwh_att_in = 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);
//V-Polarization
//Get configuration parameters
//
result_d = ConfigurationReader("name_configwbs",["hwv_laser1_s","hwv_laser2_s","hwv_heater","hwv_latchup_s"],band,0.0);
string hwv_laser1_s = "OFF";
string hwv_laser2_s = "OFF";
if(laser_V == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_V == "Laser2") {
hwv_laser2_s = "ON";
}
int hwv_heater = iround(result_d[2]{0});
string hwv_latchup_s = result_d[3]{1};
int hwv_att_band4 = 0;
int hwv_att_band3 = 0;
int hwv_att_band2 = 0;
int hwv_att_band1 = 0;
int hwv_att_in = 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);
//
//Wait delay to allow all setting to be configured
delay(wbs_config_delay);
}
//TM check when in Primary mode
procedure Mode_status_check_primary {
string laser_H = "Laser1" in ["Laser1","Laser2"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2"]; //WBS-V laser to be set ON
string chopper_loop = "OPEN" in ["OPEN","CLOSE"]; //chopper loop status
}{
mois_comment("Checking instrument status in primary mode");
//General checks: not needed here as we won't be at that stage otherwise
//FCU checks
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["calibrator_current_on"],"0",0.0);
double calibcurrent = result_d[0]{0};
//mois_tmcheck("Check that parameter HF_APR_CS_C is set to " + calibcurrent + " mA");
//mois_tmcheck("Check that parameter HF_DPR_CHLOOP_S is set to " + chopper_loop);
//WBS checks: not applicable: status unchanged
//HRS Checks: not applicable: status unchanged
//LOU Checks
mois_tmcheck("Check that parameter HL_MODE_S is normal");
mois_tmcheck("Check that parameter HL_Channel_S is Off");
}
// Treat each line separately - no optimization of consecutive lines
{int,int[]}[] procedure LcuGetMemoryRuns_ops {
string section = "P" in ["P","R"]; // select prime or redundant LCU
}{
string tab = "LcuMemoryPatch_" + section + ".config";
int total = table_size(tab);
{int,int[]}[] result = [];
for(int line = 1 .. total) {
string look = "" + line;
int loc = ilookup(tab,look,"location");
int val = ilookup(tab,look,"value");
int[] value = [];
value[0] = val;
result[line - 1] = {loc,value};
}
return result;
}
/////////////////////////////////////////////////////////////////
// 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.");
}
}
//Check consistency between band and frequency inputs
//Should be invoked at the beginning of every mode !
bool procedure Check_Band_vs_Freq_proc_fm {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
}{
bool go_ahead = true;
bool go_ahead_a = true;
bool go_ahead_b = true;
//
//Fetch LO limits
{double,string}[] result = ConfigurationReader("name_configlo_a",["lo_a_low","lo_a_high"],band,lo_freq);
double lo_a_low = result[0]{0};
double lo_a_high = result[1]{0};
result = ConfigurationReader("name_configlo_b",["lo_b_low","lo_b_high"],band,lo_freq);
double lo_b_low = result[0]{0};
double lo_b_high = result[1]{0};
//
if(band == "0" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "1a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "1b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(band == "2a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "2b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(band == "3a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "3b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(band == "4a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "4b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(band == "5a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "5b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(band == "6a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "6b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(band == "7a" && (lo_freq < lo_a_low || lo_freq > lo_a_high)) {
go_ahead_a = false;
}
if(band == "7b" && (lo_freq < lo_b_low || lo_freq > lo_b_high)) {
go_ahead_b = false;
}
if(go_ahead_a == false) {
//debug_print("go_ahead is: " + go_ahead);
error("LO frequency not within allowed range (" + lo_a_low + " to " + lo_a_high + " GHz) for band " + band);
go_ahead = go_ahead_a;
}
if(go_ahead_b == false) {
//debug_print("go_ahead is: " + go_ahead);
error("LO frequency not within allowed range (" + lo_b_low + " to " + lo_b_high + " GHz) for band " + band);
go_ahead = go_ahead_b;
}
//
//Extra check for warm operations with dummies: only limited amount of frequencies allowed in config files
//bool go_ahead_warm = Check_Band_vs_WarmFreq_proc_fm(band,lo_freq);
//bool go_ahead_warm = Check_Band_vs_WarmKeyFreq_proc_fm(band,lo_freq);
//if (go_ahead_warm == false) {
// go_ahead = go_ahead_warm;
// }
return go_ahead;
}
////////////////////////////////////////////////////
// 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);
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// CUS scripts for FPU.
// FPU FT scripts are found under fm_FT_FPU.cus
//
// DT - 17-Feb-06
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The modes
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//See fm_testmodes.cus
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The procedures
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Procedure checking and, if applicable, converting
//prime chopper sent voltage into redundant chopper sent voltage
double procedure Check_Chopper_Prime_Redundant {
double chopper_angle = 0.0; //prime chopper voltage
}{
//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"],"0",0.0);
double chop = chopper_angle;
double prime_endstop_min = result_d[4]{0};
double prime_endstop_max = result_d[5]{0};
double red_endstop_min = result_d[6]{0};
double red_endstop_max = result_d[7]{0};
//Change chopper voltage if necessary
if(result_d[0]{1} == "redundant") {
chop = result_d[3]{0} * pow(chop,2.0) + result_d[2]{0} * chop + result_d[1]{0};
}
//Now check the chopper angle is within the ranges
if(result_d[0]{1} == "prime") {
if(chop > prime_endstop_max || chop < prime_endstop_min) {
error("The chopper voltage (requested is " + chop + " V) in " + result_d[0]{1} + " mode has to be between " + prime_endstop_min + " and " + prime_endstop_max + " V.");
}
}
if(result_d[0]{1} == "redundant") {
if(chop > red_endstop_max || chop < red_endstop_min) {
error("The chopper voltage (requested is " + chop + " V) in " + result_d[0]{1} + " mode has to be between " + red_endstop_min + " and " + red_endstop_max + " V.");
}
}
return chop;
}
//HIFI-COP-X-IF-FBk-Dip - goes into dissipative mode
obs HifiEng_IF_FBk_Dip_COP {
string band = "3a" in ["3a","3b","4a","4b","6a","6b","7a","7b"]; // HIFI band
int testtime = 3600; //total test time in seconds
}{
//General parameters in use
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
double[] result_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = result_d[0];
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
//Avoid high data-rates
if(testtime % 3 == 0 && testtime % 4 == 0) {
testtime = testtime + 4;
}
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"start");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(IF_FBk_Dip_COP_proc_ops(band,lo_freq,hrs_mode,testtime,backend));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
IF_FBk_Dip_COP_proc_ops(band,lo_freq,hrs_mode,testtime,backend);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
// OBS SFT, block
procedure OBS_SEU_check_aot {
string memory_area = "PM_LOW" in ["PM_LOW","PM_HIGH","DM","EEPROM1","EEPROM2","BSW","ALL"];
}{
if(memory_area == "ALL") {
//De-activate S/S HK collection during the checks
Hifi_HIFI_Housekeeping_off();
delay(1);
}
//Parameters for PM-low: this is for OBS6.4.1
int check_start = ilookup("config_icu_memory.config","PM_LOW","start");
int check_end = ilookup("config_icu_memory.config","PM_LOW","end_or_length");
int check_crc = ilookup("config_icu_memory.config","PM_LOW","crc");
//PM_LOW check
if(memory_area == "PM_LOW" || memory_area == "ALL") {
mois_spacon("In the following TC, parameters HP231197, HP232197 and HP233197 should be treated as formal parameters");
Hifi_HIFI_check_PM_memory(check_start,check_end,check_crc);
delay(3);
mois_tmcheck("Verify that no 1,8 has been generated. Otherwise, please inform the HIFI ICC.");
}
//PM_HIGH check
if(memory_area == "PM_HIGH" || memory_area == "ALL") {
check_start = check_start + 0x3ffff;
check_end = check_end + 0x3ffff;
mois_spacon("In the following TC, parameters HP231197, HP232197 and HP233197 should be treated as formal parameters");
Hifi_HIFI_check_PM_memory(check_start,check_end,check_crc);
delay(3);
mois_tmcheck("Verify that no 1,8 has been generated. Otherwise, please inform the HIFI ICC.");
}
//PROM copy into PM (BSW) check
if(memory_area == "BSW" || memory_area == "ALL") {
check_start = ilookup("config_icu_memory.config","BSW","start");
check_end = ilookup("config_icu_memory.config","BSW","end_or_length");
check_crc = ilookup("config_icu_memory.config","BSW","crc");
mois_spacon("In the following TC, parameters HP231197, HP232197 and HP233197 should be treated as formal parameters");
Hifi_HIFI_check_PM_memory(check_start,check_end,check_crc);
delay(1);
mois_tmcheck("Verify that no 1,8 has been generated. Otherwise, please inform the HIFI ICC.");
}
//DM check
if(memory_area == "DM" || memory_area == "ALL") {
//There are three segments to consider here
check_start = ilookup("config_icu_memory.config","DM1","start");
int check_length = ilookup("config_icu_memory.config","DM1","end_or_length");
mois_spacon("In the following TCs, parameters HP003197 and HP004197 should be treated as formal parameters");
Hifi_HIFI_check_memory("DM",check_start,check_length);
delay(1);
//
check_start = ilookup("config_icu_memory.config","DM2","start");
check_length = ilookup("config_icu_memory.config","DM2","end_or_length");
Hifi_HIFI_check_memory("DM",check_start,check_length);
delay(1);
//
check_start = ilookup("config_icu_memory.config","DM3","start");
check_length = ilookup("config_icu_memory.config","DM3","end_or_length");
Hifi_HIFI_check_memory("DM",check_start,check_length);
delay(1);
//
}
//EEPROM1 check: done in two chunks due to length limit to 16 bits
if(memory_area == "EEPROM1" || memory_area == "ALL") {
check_start = ilookup("config_icu_memory.config","EEPROM1_1","start");
check_length = ilookup("config_icu_memory.config","EEPROM1_1","end_or_length");
mois_spacon("In the following TC, parameters HP003197 and HP004197 should be treated as formal parameters");
Hifi_HIFI_check_memory("EEPROM",check_start,check_length);
delay(1);
check_start = ilookup("config_icu_memory.config","EEPROM1_2","start");
check_length = ilookup("config_icu_memory.config","EEPROM1_2","end_or_length");
mois_spacon("In the following TC, parameters HP003197 and HP004197 should be treated as formal parameters");
Hifi_HIFI_check_memory("EEPROM",check_start,check_length);
delay(1);
}
//EEPROM2 check: done in two chunks due to length limit to 16 bits
if(memory_area == "EEPROM2" || memory_area == "ALL") {
check_start = ilookup("config_icu_memory.config","EEPROM2_1","start");
check_length = ilookup("config_icu_memory.config","EEPROM2_1","end_or_length");
mois_spacon("In the following TC, parameters HP003197 and HP004197 should be treated as formal parameters");
Hifi_HIFI_check_memory("EEPROM",check_start,check_length);
delay(1);
check_start = ilookup("config_icu_memory.config","EEPROM2_2","start");
check_length = ilookup("config_icu_memory.config","EEPROM2_2","end_or_length");
mois_spacon("In the following TC, parameters HP003197 and HP004197 should be treated as formal parameters");
Hifi_HIFI_check_memory("EEPROM",check_start,check_length);
delay(1);
}
//
if(memory_area == "ALL") {
//Re-activate S/S HK collection during the checks
Hifi_HIFI_Housekeeping_on("1_pkt_per_s","ON","ON","ON","ON","ON","ON");
}
}
//HIFI-COP-3-FTP
procedure FT_pumped_COP_proc_ops {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
int integ_time = 4;
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
}{
//
//Get list of frequencies for given band
double[] cresult = CalibrationReader("name_keyfreq",["keyfreq","minfreq","maxfreq","midfreq","badfreq"],band,0.0);
//
string current_subband = "0";
//Loop on key frequencies per LO band
for(int i = 0 .. 4) {
//
//Wait an extra delay of 1 min for short term stabilization
delay(60);
Init_MSA_HBB_fm(band,"CLOSE",cresult[i],"ON");
LO_tuning_block_fm(band,cresult[i]);
//
FT_pumped(band,hrs_mode,integ_time,backend,cresult[i]);
//
//switch-off LO
LCU_switch_off_block_fm();
//
FT_unpumped(band,hrs_mode,integ_time,backend);
}
//
}
////////////////////////////////////////////////////////////////////////////
// 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();
}
}
}
//Set LCU5a back to standby status, procedure
procedure LCU5a_standby_proc_fm {
string band = "5a"; // HIFI band
double lo_freq = 1150.0 in [1127.0,1178.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
//LO disable in manual commanding
mode HifiManCmd_LO_disable {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to disable the LOU S/S");
StartMode_block_ops();
//
mois_step("Disable LOU");
LCU_disable_all_bands_block_fm();
//
StopMode_block_mois();
// -> to issue last obsd/bbid
}
//HIFI LO tuning only for M1 and M2 investigation in 7b, block
//Target current is read from look-up table
block LO_tuning_w_M1M2_block_fm HIFI 3718 {
string band = "7b"; // HIFI band
double lo_freq = 1890.0; //LO frequency
double m1 = -5.0; //M1 multiplier voltage
double m2 = -11.0; //M2 multiplier voltage
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Start_block();
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//
//Get target mixer current
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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],band,lo_freq);
double plevel_v = result[0]{0};
double m1_v = m1;
//result[1]{0};
double m2_v = m2;
//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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = result[1]{1};
//
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};
//
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,lo_freq);
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);
//The automatic tuning shall use the min of the nominal best-guess and Vd2max - 100mV
double middle_d2 = min(result[0]{0},drain2_bluemax - 0.1);
double drain2_v_start = min(middle_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) * middle_d2;
//drain2_v_start;
step_drain2_v = (drain2_v_end - drain2_v_start) / double(nsteps - 1);
//
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
//Send command
if(band == "3b") {
Hifi_HIFI_Conf_nom_LCU_ch3b($BBID,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);
//Send command: specific to M3 in 3b
delay(config_lo_delay);
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
} else {
//
//General command
HIFI_Configure_LCU_proc_fm(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);
}
//
//delay(5); //to settle at this value
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "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_nom_3b($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 == "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);
}
//
delay(1);
//
//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
HIFI_HL_store_tm_only_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The blocks
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Diplexer scan, fast, block.
// Mixer current as function of diplexer current. Takes 1 seconds per point
// IT IS THE OBSOLETE VERSION NOT MAKING USE OF THE DEDICATED OBS TC
block Diplexer_scan_fast_fm HIFI 3251 {
string band = "3a"; // HIFI band
double diplexer_current_min_h = -2.24; //minimum diplexer current H
double diplexer_current_max_h = 2.24; //maximum diplexer current H
double diplexer_current_min_v = -2.24; //minimum diplexer current V
double diplexer_current_max_v = 2.24; //maximum diplexer current V
int n_steps = 100; //number of steps
}{
Start_block();
int steps = 0;
int steps_done = 0;
int steps_wanted = n_steps;
if(steps_wanted < 1) {
steps_wanted = 1;
}
double diplexer_current_h = 0.0;
double diplexer_current_v = 0.0;
double stepsize_h = 0.0;
double stepsize_v = 0.0;
//
if(steps_wanted > 1) {
stepsize_h = (diplexer_current_max_h - diplexer_current_min_h) / (double(steps_wanted) - 1.0);
stepsize_v = (diplexer_current_max_v - diplexer_current_min_v) / (double(steps_wanted) - 1.0);
}
while(steps_done < steps_wanted) {
steps = steps_wanted - steps_done;
if(steps > n_steps) {
steps = n_steps;
}
diplexer_current_h = diplexer_current_min_h + double(steps_done) * stepsize_h;
Hifi_HIFI_CH1_DPACT_C($BBID,diplexer_current_h);
//Sets H diplexer current
diplexer_current_v = diplexer_current_min_v + double(steps_done) * stepsize_v;
Hifi_HIFI_CV1_DPACT_C($BBID,diplexer_current_v);
//Sets V diplexer current
//
delay(1);
steps_done = steps_done + 1;
}
}
// 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;
}
// HRS linearity check, loop on individual attenuators, mode
// This is the COP version where no WBS is considered
// =======================================================
block HRS_linearity_indiv_block_cop HIFI 3960 {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total integration time in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//Fetch resistive bias
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_high_resistive_h","bias_high_resistive_v","bias_medium_resistive_h","bias_medium_resistive_v"],band,0.0);
//
double bias_high_h = result[0]{0};
double bias_high_v = result[1]{0};
double bias_medium_h = result[2]{0};
double bias_medium_v = result[3]{0};
int repeats = 32;
double hrsH_attenuators_value = 15.5;
double hrsV_attenuators_value = 15.5;
//Test will be done in WB mode for both polar
string hrsh_blocks_configuration = "corr_wide";
string hrsv_blocks_configuration = "corr_wide";
// Configure spectroscopy
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
// Configure blocks
//=================
//H-polar
Hifi_HIFI_Config_HRS_H_blocks($BBID,hrsh_blocks_configuration,hrsh_blocks_configuration,hrsh_blocks_configuration,hrsh_blocks_configuration,hrsh_blocks_configuration,hrsh_blocks_configuration,hrsh_blocks_configuration,hrsh_blocks_configuration);
//
//delay(1);
//V-polar
Hifi_HIFI_Config_HRS_V_blocks($BBID,hrsv_blocks_configuration,hrsv_blocks_configuration,hrsv_blocks_configuration,hrsv_blocks_configuration,hrsv_blocks_configuration,hrsv_blocks_configuration,hrsv_blocks_configuration,hrsv_blocks_configuration);
//
delay(1);
// Fetch internal LO settings
//===========================
//H-polar
string hrs_filename_h = "name_confighrs_" + hrs_mode[0];
result = ConfigurationReader(hrs_filename_h,["hrh_switch","hrh_up_ol1","hrh_up_ol2","hrh_up_ol3","hrh_up_ol4","hrh_down_ol5","hrh_down_ol6","hrh_down_ol7"],band,0.0);
double[] hrsH_LO = [result[1]{0},result[2]{0},result[3]{0},result[4]{0},result[5]{0},result[6]{0},result[7]{0}];
string hrs_polarization_h = result[0]{1};
//V-polar
string hrs_filename_v = "name_confighrs_" + hrs_mode[1];
result = ConfigurationReader(hrs_filename_v,["hrv_switch","hrv_up_ol1","hrv_up_ol2","hrv_up_ol3","hrv_up_ol4","hrv_down_ol5","hrv_down_ol6","hrv_down_ol7"],band,0.0);
double[] hrsV_LO = [result[1]{0},result[2]{0},result[3]{0},result[4]{0},result[5]{0},result[6]{0},result[7]{0}];
string hrs_polarization_v = result[0]{1};
//
//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 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];
//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];
//
///////////////////////////////////////
//
// Loops on the different configurations of the HRS attenuators
//===============================================
//Magnets shall be set to 0 since high biases will be used
Set_Magnet_current_proc_fm(0.0,0.0);
//
for(int i = 0 .. repeats - 1) {
// Configure attenuators and LO
//=============================
Hifi_HIFI_Config_HRS_H_att_lo($BBID,hrs_polarization_h,hrsH_attenuators_value,hrsH_attenuators_value,hrsH_attenuators_value,hrsH_attenuators_value,hrsH_attenuators_value,hrsH_attenuators_value,hrsH_attenuators_value,hrsH_attenuators_value,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(2);
Hifi_HIFI_Config_HRS_V_att_lo($BBID,hrs_polarization_v,hrsH_attenuators_value,hrsV_attenuators_value,hrsV_attenuators_value,hrsV_attenuators_value,hrsV_attenuators_value,hrsV_attenuators_value,hrsV_attenuators_value,hrsV_attenuators_value,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(1);
//
//Set the shot noise to high resistive bias
Mixerbias(bias_high_h,bias_high_v);
// Take spectrum
//==============
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//
//Set the shot noise to medium resistive bias
Mixerbias(bias_medium_h,bias_medium_v);
// Take spectrum
//==============
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
// Change the value of the 8 attenuators
//======================================
hrsH_attenuators_value = hrsH_attenuators_value - 0.5;
hrsV_attenuators_value = hrsV_attenuators_value - 0.5;
}
//
}
/////////////////////////////////////////////////////////////////
// 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_on = 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_on = wshort * tdeadother_on + 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};
// treat integration times of other frequencies as dead time
double tdeadother_off = double(data_time_off * 2 * n_chop_off);
// 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(grouplen * n_cycles);
wshort = double(n_cycles * grouplen - numlong_off) / double(grouplen * n_cycles);
tdeadint_off = wlong * tdeadlong + wshort * tdeadint_off;
tphaseint_off = (wlong * tinst{0} + wshort * tphaseint_off) / (2.0 * avnumchop_off);
tdeadother_off = wshort * tdeadother_off + double(data_time_off * 2 * n_long_off) * wlong;
} 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(grouplen * 2 * data_time_off) * avnumchop_off;
double tdead_tot = tdead + tdeadint_on + tdeadint_off;
// Add integration times of other frequencies as dead time
tdead_tot = tdead_tot + double(grouplen - 1) * (tdeadother_on + tdeadother_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 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);
// 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,false,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(n_load_on > 0) {
// First load
SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,false,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,false,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,false,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
// Get appropriate settings for selected HIFI band
double[] x = CalibrationReader("backendselect",["window1_lo","window1_up","window2_lo","window2_up","window3_lo","window3_up","window4_lo","window4_up"],band,0.0);
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])]];
{bool,int[][]} wbs1 = {wbs1_used,stdWbsWindows};
{bool,int[][]} wbs2 = {wbs2_used,stdWbsWindows};
// 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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Single Point - Frequency Switch noRef",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
// Vector scan calibration for a given LO band
// Ues domains of frequencies to be scanned for each LO sub-band
procedure Vecscan_calibration_proc_fm_COP {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//
LCU_switchon_proc_fm(band);
//Wait an extra delay of 1 min for short term stabilization
delay(60);
//
//Get the list of frequencies to be used for the scan
string tab = "config_vecscan.config";
double bandnb = GetBandCode(band);
double lofreqlow = dlookup(tab,"" + iceil(bandnb),"lofreqlow");
double lofreqhigh = dlookup(tab,"" + iceil(bandnb),"lofreqhigh");
double lofreqstep = dlookup(tab,"" + iceil(bandnb),"lofreqstep");
//
double current_LO = lofreqlow;
bool endreached = false;
//Loop on key frequencies per LO band
while(current_LO <= lofreqhigh && endreached == false) {
//Configure FPU at that frequency
//SPR-2463: look at HBB
Init_MSA_HBB_fm(band,"CLOSE",current_LO,"ON");
//
//Perform vector scan within BLUE limits at that frequency
Vector_scan_BLUE_LIMIT_block_fm(band,current_LO);
//LCU_CLEAR_ERROR_block_fm();
//
//sanity check
//double[] result_dip = Get_Diplexer_setting(band,current_LO);
message("LO freq " + current_LO);
//Check last LO freq done
if(current_LO == lofreqhigh && endreached == false) {
endreached = true;
}
//Increase LO freq: truncate if step too high
current_LO = current_LO + lofreqstep;
if(current_LO > lofreqhigh && endreached == false) {
current_LO = lofreqhigh;
}
}
//
}
//HIFI LO tuning, block
//Target current in entered as input parameter
block LO_tuning_w_targetC_bestguess_block_fm HIFI 3728 {
double target_current = 0.025; //Target mixer current
double bestguess = 1.6; //Bestguess Vd2
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
string mixer_polarization = "H" in ["H","V"]; //The polarization to be used for the tuning
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Start_block();
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
//mixer_polarization = result[0]{1};
//Get target mixer current: from input
//
//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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = result[1]{1};
//
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};
//
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,lo_freq);
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 middle_d2 = bestguess;
//result[0]{0};
double drain2_v_start = min(middle_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);
//
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
//Send command
HIFI_Configure_LCU_proc_fm(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);
//
//delay(5); //to settle at this value
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
/////////////////////////////////////////////////////////////////
// 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,"fs",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 readoutdead = SlowChopReadoutDelay(band,reffreq,backendreadoutparms);
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,true);
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));
tunediff = ComputeLOTimeDifference(band,lo_freq_low,lo_freq_up,reffreq,false);
smallstep = smallstep + 2 * tunediff;
} else {
smallstep = bigtunestep;
}
int grouptime = n_freq_point * on_inttime + (n_freq_point - 1) * smallstep;
// Duration of initial set up
// Staying at the same frequency makes no sense here.
// First frequency point
double runningfreq = freqgrid[grouporder[0][0]];
// Compute load integration time
int loadlength = duration(SScanDoubleLoadMeasurement(band,runningfreq,reffreq,freq_throw,true,eff_resolution{0},data_time,backendreadoutparms));
loadlength = loadlength + readoutdead;
// 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;
// recompute load length during slews - no retuning
loadlength = duration(SScanDoubleLoadMeasurement(band,reffreq,reffreq,freq_throw,false,eff_resolution{0},data_time,backendreadoutparms));
loadlength = loadlength + readoutdead;
// 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;
} 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};
}
////////////////////////////////////////
// Standing wave on the Imix
// no-spectra version
procedure Standing_wave_nospectra_fm_COP {
string band = "1a"; // HIFI band
double[] lo_freq_input = [500.0,500.15,0.02]; //Start, end and step lo_freq for the LO scan
}{
// Initial LO tuning at centre frequency of scan
//
double lo_freq_ref = (lo_freq_input[0] + lo_freq_input[1]) / 2.0;
LO_tuning_block_fm(band,lo_freq_ref);
double lo_freq = lo_freq_input[0];
//Loop on LO frequencies. It is assumed that the LO is tuned at the middle frequency of the scan
//
int nbstep = 0;
//For freq above 1THz rounding makes miss the last step.
double margin = 0.1 / 1.0E9;
//0.1Hz
while(lo_freq <= lo_freq_input[1] + margin) {
//Set synthesizer to new LO freq.
LCU_config_nominal_noretune_block_fm(band,lo_freq,lo_freq_ref);
//
//Increase lo_freq
lo_freq = lo_freq + lo_freq_input[2];
nbstep = nbstep + 1;
}
message("LO freq: " + lo_freq_ref + "Nb of steps: " + nbstep);
}
//////////////////////////////////////////////////////////////////////
// Compatibility procedure to provide the same API as used in
// the previous versions
//
// Returns the actual integration time and the dead time per phase
{{double,double,double},{int,int}} procedure ConfigSpectroscopyFastChop_IST {
/* Integration time */
double data_chop = 0.5 in [0.1,2.0]; // Length of a single chop phase
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 = "1a"; // HIFI band
double lo_freq = 522000.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}
}{
// Translate data_chop into new parameter data_time (approximate)
// Get auxiliary quantities
{double,string}[] result = ConfigurationReader("name_delays",["add_wbs","add_jitter","wbs_readout","wbs_init"],band,lo_freq);
int add_wbs = iround(result[0]{0});
int add_jitter = iround(result[1]{0});
int wbs_readout = iround(result[2]{0});
int wbs_init = iround(result[3]{0});
int tdead_data = 2 * (wbs_readout + add_jitter) + add_wbs - add_jitter;
int totaltime = (iceil(1000.0 * data_chop) * 2 * n_int + tdead_data) * n_data + wbs_init;
totaltime = iceil(double(totaltime) / 1000.0);
int data_time = (totaltime + n_data - 1) / n_data;
// Check
CheckFastChopFrequency(band,lo_freq,data_time,n_int,n_data);
// 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_IST(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 tdead_chop = timing{10};
tdead_data = timing{11};
int tint_act = timing{12};
{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);
//
// Return dead times and comand parameters
return {{double(tint_act) / 1000.0,double(tdead_chop) / 1000.0,double(data_time * n_data)},{n_wbs1,n_hrs_trans}};
}
// Spectrometer configuration for slow chop, low level procedure
int[] procedure Configure_Spectrometer_slow_chop_proc_fm {
string band = "1a"; // HIFI band
int integ_time = 8; //Total integration time in sec. for the two phases !
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,wb5
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//First derive backend setting codes as expected by VO's routine
//Build up backend parameter tupple:
{{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = BackendSettings(band,0.0,hrs_mode,backend);
// Readout parameters for HRS1,HRS2, WBS1,WBS2
//Compute data_time and n_switch use the wrapper
int[] res = ConfigSlowChop(integ_time,"chop",band,0.0,backendreadoutparms);
int data_time = res[0];
int n_switch = res[1];
// Now call the spectroscopy setup: it is common to ILT and AOT CUS.
// The deadtimes output is not used at ILT level.
{double,double} dtimes = ConfigSpectroscopySlowChop_IST(data_time,n_switch,"chop",band,0.0,backendreadoutparms,true);
//
return res;
}
//HIFI-COP-3-Stab-1
//This one should be use for preparation via XHSpot
//It assumes one obsid per band/stab_category/freq
obs HifiEng_Stab_COP {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string stab = "sys" in ["sys","lsw","int","dbs","fsw","stab"]; //category of stability measurement
int freq_index = 1; //Frequency index to be applied
int throw_index = 1; //FSW throw index to be applied
}{
//General parameters in use
string[] hrs_mode = ["wb1","wb1"];
int integ_time = 4;
double chop_phase = 1.0;
string shutter = "open";
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Stab_COP_proc_ops(band,stab,freq_index,throw_index,hrs_mode,integ_time,chop_phase,shutter));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Stab_COP_proc_ops(band,stab,freq_index,throw_index,hrs_mode,integ_time,chop_phase,shutter);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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();
}
}
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The procedures
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Mode initialisation
procedure StartMode {
}{
BroadcastOBSID();
//Get applicable HK rate
{double,string}[] result_d = ConfigurationReader("name_delays",["hk_rate"],"0",0.0);
double hk_rate = result_d[0]{0};
HKrate(hk_rate);
}
// BLOCK : Functional Test No 1 (HRS Master Reset)
block HRS_functional_test_No_1_block_fm HIFI 3611 {
}{
//Start_block();
//
//Use new command implemented in SCR-859
Hifi_HIFI_HRS_functional_test($BBID,1,"BOTH");
delay(5);
//
}
// 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);
}
// 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;
}
// 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);
}
// Initialisation of FPU, block with both MSA in use
// It is for cold context !
// It can control the diplexer filter
block Init_MSA_DipFilter_fm HIFI 3954 {
string band = "1a"; // HIFI band
string chop_loop = "CLOSE";
double lo_freq = 522.0; //LO frequency
string hbb_heater = "ON" in ["ON","OFF"]; //hot source on/off
int diplex_h_ctrl_mode = 227; //Diplexer filter
}{
Start_block();
//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 = diplex_h_ctrl_mode;
//
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,0.0);
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.
//chopper = Check_Chopper_Prime_Redundant(chopper);
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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,lo_freq);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
//In case of band 6 or 7, bias have been set to 4mV. Now set to nominal
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq);
Mixerbias(result[0]{0},result[1]{0});
}
//
//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);
}
//
//Hifi_HIFI_non_periodic_hk_FCU ();
}
//Filler procedure to generate TPF for Spurious tests
//We use a TC that calls only the BBID, pass the currents
//frequency param, and Vd2
//Its value will corrected after IPF generation
procedure COP_Spur_TPF_maker {
string band = "3b" in ["3b","7b"]; // HIFI band
int testblock = 1 in [0,3]; //Test block for 3b
}{
int bbid = 1;
string name_confindex = "name_confindex_b";
string name_configlcu = "name_configlcu_b";
//We will loop on tabulated frequencies
//For each we will tune LO power and do diplexer scans
//for 5-8 M1 settings
//1. Get the list of frequencies to be used for the scan
string tab1 = "config_M1calib_" + band + "_" + testblock + ".config";
if(testblock == 0) {
tab1 = "config_M1calib_" + band + "_COP.config";
string tab2 = "config_M2calib_" + band + "_COP.config";
}
int total = table_size(tab1);
double[] freq = [];
double[] m1_1 = [];
double[] m1_2 = [];
double[] m1_3 = [];
double[] m1_4 = [];
double[] m1_5 = [];
double[] m1_6 = [];
double[] m1_7 = [];
double[] m1_8 = [];
double[] m2 = [];
double[] m3 = [];
for(int j = 1 .. total) {
if(band == "7b") {
freq[j] = dlookup(tab1,"" + j,"frequency");
m1_1[j] = dlookup(tab1,"" + j,"m1_1");
m1_2[j] = dlookup(tab1,"" + j,"m1_2");
m1_3[j] = dlookup(tab1,"" + j,"m1_3");
m1_4[j] = dlookup(tab1,"" + j,"m1_4");
m1_5[j] = dlookup(tab1,"" + j,"m1_5");
//Get frequency parameters
{double,string}[] result = ConfigurationReader(name_confindex,["freq_nx"],band,freq[j]);
int freq_nx = ifloor(result[0]{0});
//Compute lsu_main and offset
int[] resu = ComputeLSU_A_M_R(band,freq[j]);
int lsu_main = resu[0];
int lsu_offset = resu[1];
//Get max Vd2
double drain2_bluemax = Get_BLUE_LIMIT_D2_proc_fm(band,freq[j]);
//Convert into raw:
int vd2 = convert_to_raw("hifi_HL_Drain2_7B_V",drain2_bluemax);
int mm1_1 = convert_to_raw("hifi_HL_M1_7B_V",m1_1[j]);
int mm1_2 = convert_to_raw("hifi_HL_M1_7B_V",m1_2[j]);
int mm1_3 = convert_to_raw("hifi_HL_M1_7B_V",m1_3[j]);
int mm1_4 = convert_to_raw("hifi_HL_M1_7B_V",m1_4[j]);
int mm1_5 = convert_to_raw("hifi_HL_M1_7B_V",m1_5[j]);
Hifi_HIFI_WBS_Zero(mm1_1);
Hifi_HIFI_WBS_Zero(mm1_1);
Hifi_HIFI_WBS_Zero(mm1_1);
Hifi_HIFI_WBS_Zero(mm1_2);
Hifi_HIFI_WBS_Zero(mm1_2);
Hifi_HIFI_WBS_Zero(mm1_2);
Hifi_HIFI_WBS_Zero(mm1_3);
Hifi_HIFI_WBS_Zero(mm1_3);
Hifi_HIFI_WBS_Zero(mm1_3);
Hifi_HIFI_WBS_Zero(mm1_4);
Hifi_HIFI_WBS_Zero(mm1_4);
Hifi_HIFI_WBS_Zero(mm1_4);
Hifi_HIFI_WBS_Zero(mm1_5);
Hifi_HIFI_WBS_Zero(mm1_5);
Hifi_HIFI_WBS_Zero(mm1_5);
}
if(band == "3b") {
freq[j] = dlookup(tab1,"" + j,"frequency");
m1_1[j] = dlookup(tab1,"" + j,"m1_1");
m1_2[j] = dlookup(tab1,"" + j,"m1_2");
m1_3[j] = dlookup(tab1,"" + j,"m1_3");
m1_4[j] = dlookup(tab1,"" + j,"m1_4");
m1_5[j] = dlookup(tab1,"" + j,"m1_5");
m1_6[j] = dlookup(tab1,"" + j,"m1_6");
m1_7[j] = dlookup(tab1,"" + j,"m1_7");
//m1_8[j] = dlookup(tab1,"" + j,"m1_8");
if(testblock > 0) {
m2[j] = dlookup(tab1,"" + j,"m2_" + testblock);
m3[j] = dlookup(tab1,"" + j,"m3_" + testblock);
} else {
m2[j] = dlookup(tab2,"" + j,"m2_1");
m3[j] = dlookup(tab2,"" + j,"m3_1");
}
//Get frequency parameters
result = ConfigurationReader(name_confindex,["freq_nx"],band,freq[j]);
freq_nx = ifloor(result[0]{0});
//Compute lsu_main and offset
resu = ComputeLSU_A_M_R(band,freq[j]);
lsu_main = resu[0];
lsu_offset = resu[1];
//Get gates and drain1
double[] cresult = CalibrationReader("name_lcu_safe_values",["g1_v","g2_v","d1_v"],band,freq[j]);
double gate1_v = cresult[0];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
result = ConfigurationReader(name_configlcu,["gate1_v"],band,freq[j]);
gate1_v = result[0]{0};
}
//
double gate2_v = cresult[1];
double drain1_v = cresult[2];
//Get curlims
result = ConfigurationReader("name_configlo_b",["curlim1_v","curlim2_v"],band,freq[j]);
string curlim1 = result[0]{1};
string curlim2 = result[1]{1};
//Get max Vd2
drain2_bluemax = Get_BLUE_LIMIT_D2_proc_fm(band,freq[j]);
//Convert into raw:
int g1 = convert_to_raw("hifi_HL_Gate1_3B_V",gate1_v);
int g2 = convert_to_raw("hifi_HL_Gate2_3B_V",gate2_v);
int vd1 = convert_to_raw("hifi_HL_Drain1_3B_V",drain1_v);
//convert_to_raw does not work for params defined through TextualCalibrationCurves
//The convertion is:
if(curlim1 == "1.5") {
int curl1 = 0;
}
if(curlim1 == "1.4") {
curl1 = 2;
}
if(curlim1 == "1.3") {
curl1 = 1;
}
if(curlim1 == "1.22") {
curl1 = 3;
}
//
if(curlim2 == "1.5") {
int curl2 = 0;
}
if(curlim2 == "1.4") {
curl2 = 2;
}
if(curlim2 == "1.3") {
curl2 = 1;
}
if(curlim2 == "1.22") {
curl2 = 3;
}
vd2 = convert_to_raw("hifi_HL_Drain2_3B_V",drain2_bluemax);
mm1_1 = convert_to_raw("hifi_HL_M1_3B_V",m1_1[j]);
mm1_2 = convert_to_raw("hifi_HL_M1_3B_V",m1_2[j]);
mm1_3 = convert_to_raw("hifi_HL_M1_3B_V",m1_3[j]);
mm1_4 = convert_to_raw("hifi_HL_M1_3B_V",m1_4[j]);
mm1_5 = convert_to_raw("hifi_HL_M1_3B_V",m1_5[j]);
int mm1_6 = convert_to_raw("hifi_HL_M1_3B_V",m1_6[j]);
int mm1_7 = convert_to_raw("hifi_HL_M1_3B_V",m1_7[j]);
//int mm1_8 = convert_to_raw("hifi_HL_M1_3B_V",m1_8[j]);
int mm2 = convert_to_raw("hifi_HL_M2_3B_V",m2[j]);
int mm3 = convert_to_raw("hifi_HL_M3_3B_V",m3[j]);
int mm2_generic = mm2;
if(testblock == 2) {
mm2_generic = mm2;
}
if(testblock == 3) {
mm2_generic = mm2;
}
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_1);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_2);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_3);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_4);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_5);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_6);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
//Hifi_HIFI_WBS_Zero(freq_nx);
//Hifi_HIFI_WBS_Zero(lsu_main);
//Hifi_HIFI_WBS_Zero(lsu_offset);
Hifi_HIFI_WBS_Zero(mm1_7);
Hifi_HIFI_WBS_Zero(mm2_generic);
Hifi_HIFI_WBS_Zero(mm3);
Hifi_HIFI_WBS_Zero(g1);
Hifi_HIFI_WBS_Zero(g2);
Hifi_HIFI_WBS_Zero(vd1);
Hifi_HIFI_WBS_Zero(curl1);
Hifi_HIFI_WBS_Zero(vd2);
Hifi_HIFI_WBS_Zero(curl2);
}
}
//
}
// Chop between internal and external cold loads, block
// We take 1 spectrum per phase.
block Stability_intcold_extcold_fm HIFI 3424 {
string band = "1a"; // HIFI band
int n = 100; //The number of integration pairs
int integ_time = 4; //Total (co-added) integration time of ONE SINGLE phase in sec.
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string chopmode = "slowchop" in ["slowchop","fastchop"]; //Whether to use slowchop or fastchop
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length
}{
Start_block();
//Shutter_rotate_proc_fm("closed");
//Get chopper settings
{double,string}[] result = ConfigurationReader("name_confilfpu",["chop_M3","chop_cold"],band,0.0);
double chop_middle = result[0]{0};
double chop_cold = result[1]{0};
//
//We implement a special slow-chop spectroscopy between
//internal cold and external cold
if(chopmode == "slowchop") {
Slow_chop_spectro_for_Stability_proc_fm(band,n,integ_time * 2,backend,hrs_mode,chop_middle,chop_cold);
} else {
Fast_chop_spectro_for_Stability_proc_fm(band,n,integ_time * 2,backend,hrs_mode,chop_middle,chop_cold,chop_phase);
}
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
/////////////////////////////////////////
block FCU_config_mxdp_block_fm HIFI 3990 {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 522.0; //LO frequency
}{
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["band"],band,lo_freq);
int band_nb = iround(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 diplexer currents
if(band_nb <= 2 || band_nb == 5) {
double diplex_H = 0.0;
//For bands 1, 2 and 5
double diplex_V = 0.0;
} else {
double[] result_dip = Get_Diplexer_setting(band,lo_freq);
diplex_H = result_dip[0];
diplex_V = result_dip[1];
}
//
Hifi_HIFI_Config_mxbias_dpact($BBID,bias_H,bias_V,diplex_H,diplex_V);
delay(1);
//
//In case of band 6 or 7, bias have been set to 4mV. 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});
}
//
}
//Band5
//LO parameter scan with HotCold measurement
//for Band 5a
procedure LCU5a_power_scan_with_Tsys {
string band = "5a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4
double lo_freq = 1150.0 in [1127.0,1178.0]; //LO frequency
double param_min = 1.0; //Min. of scanned parameter
double param_max = 2.0; //Max. of scanned parameter
double step_size = 0.1; //Step size
string param_name = "D2"; //Code of scanned parameter: M1,M2,M3,G1,G2,D1,D2.
int integ_time = 4; //Total integration time in sec.
}{
error("This module is obsolete: use LCU_power_scan_with_Tsys instead");
}
//PDU switch off of a S/S, block
block PDU_switch_off_block_ops HIFI 7659 {
string subsystem = "ICU_Prime" in ["ICU_Prime","ICU_Red","LO_Prime","LO_Red","WBS_H","WBS_V","HRS_H","HRS_V"];
}{
if(subsystem != "ICU_Prime" && subsystem != "ICU_Red") {
StartBlock_ops();
//This has no delay
}
////HifiIltEgse_PDU_switch_off($BBID,subsystem); //The TEI command: WILL BE DONE BY SPACON
mois_spacon("Please power OFF Sub-System " + subsystem);
//delay(1);
}
//////////////////////////////////////////////////////////////////
// HRS complete configuration with maximum attenuation, block
// Both polarizations are treated
block HRS_config_max_att_block_fm HIFI 3634 {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
}{
//Start_block();
// 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);
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
// OBS SFT, mode
mode HifiManCmd_OBS_SFT {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
Mode_status_check_intermediate();
StartMode_block_ops();
mois_comment("Start On-Board Software SFT");
OBS_SFT_block_ops();
StopMode_block_mois();
}
//Set LCU2b back to standby status, procedure
procedure LCU2b_standby_proc_fm {
string band = "2b"; // HIFI band
double lo_freq = 750.0 in [724.0,793.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
//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;
}
//////////////////////////////////////////////////////////
// Nominal configuration
/////////////////////////
// LCU configuration AT START-UP into NOMINAL mode, procedure
procedure LCU_switchon_proc_fm {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//Clear potential failure mode
Set_LO_Nominal_block_fm();
//
//We use a constant frequency for each band, regardless of the input
double lo_freq = 0.0;
double[] result_d = CalibrationReader("name_keyfreq",["keyfreq","midfreq","keyfreqwarm","keyfreq_dummy"],band,0.0);
lo_freq = result_d[0];
//this is for cold operations
// lo_freq = result_d[2]; //this is for warm operations
// lo_freq = result_d[3]; //this is for dummy operations
////FM_CUS_11.5: replace keyfreq by the only allowed frequency for warm IST
//For band 7b, 1723.5 may be problematic. Take mid freq. instead
//if (band == "7b") {
// lo_freq = result_d[1];
// }
//
//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","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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",["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});
//
cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lo_freq);
drain2_v = cresult[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_fm(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);
//
//Set heater to their switch-on value
HL_heater_block_fm(band,"nominal");
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// CUS scripts for HRS.
// HRS FT scripts are found under fm_FT_HRS.cus
//
// DT - 17-Feb-06
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The modes
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// See fm_testmodes.cus
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The blocks
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// HRS polar switch test - scenario proposed by NDW, block
procedure HRS_polar_switch_proc_fm {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
}{
//
//Get biases. No LO freq. given here.
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_low_resistive_h","bias_high_resistive_h","bias_low_resistive_v","bias_high_resistive_v"],band,0.0);
double bias_low_h = result[0]{0};
double bias_high_h = result[1]{0};
double bias_low_v = result[2]{0};
double bias_high_v = result[3]{0};
//
//some global settings
int integ_time = 4;
string backend = "hrs";
//Prepare magnets
Set_Magnet_current_block_fm(0.0,0.0);
//Set biases to 10mV - SPR-2110
Mixerbias_block_fm(bias_high_h,bias_high_v);
//
//1. Configure HRS with normal switches: HRH on H, HRV on V
HRS_config_w_switch_block_fm(band,hrs_mode,["H","V"]);
//tune and take IF noise measurement
HRS_tune_block_fm(band);
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//Take 5 and 10mV shot noise spectra
Spectra_resistive_low_fm(band,bias_low_h,bias_low_v,integ_time,backend);
Spectra_resistive_high_fm(band,bias_high_h,bias_high_v,integ_time,backend);
//
//2. Configure HRS with new switches: HRH on H, HRV on H
HRS_config_w_switch_block_fm(band,hrs_mode,["H","H"]);
//tune and take IF noise measurement
HRS_tune_block_fm(band);
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//Take 5 and 10mV shot noise spectra
Spectra_resistive_low_fm(band,bias_low_h,bias_low_v,integ_time,backend);
Spectra_resistive_high_fm(band,bias_high_h,bias_high_v,integ_time,backend);
//
//3. Configure HRS with new switches: HRH on V, HRV on V
HRS_config_w_switch_block_fm(band,hrs_mode,["V","V"]);
//tune and take IF noise measurement
HRS_tune_block_fm(band);
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//Take 5 and 10mV shot noise spectra
Spectra_resistive_low_fm(band,bias_low_h,bias_low_v,integ_time,backend);
Spectra_resistive_high_fm(band,bias_high_h,bias_high_v,integ_time,backend);
//
//4. back to standard setting
//Need a representative frequency: take keyfreq
double[] result_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = result_d[0];
result = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v","norm_bias_h","norm_bias_v"],band,lo_freq);
double magnet_h = result[0]{0};
double magnet_v = result[1]{0};
double bias_h = result[2]{0};
double bias_v = result[3]{0};
HRS_config_w_switch_block_fm(band,hrs_mode,["H","V"]);
Mixerbias_block_fm(bias_h,bias_v);
Set_Magnet_current_block_fm(magnet_h,magnet_v);
}
// WBS reset, block
// Both polarizations are treated
block WBS_reset_block_fm HIFI 3602 {
}{
//Fetch applicable HK rate
{double,string}[] result_d = ConfigurationReader("name_delays",["hk_rate"],"0",0.0);
string hk_rate = result_d[0]{1};
//Switch off HK request on WBS
Hifi_HIFI_Housekeeping_on(hk_rate,"ON","ON","OFF","OFF","ON","ON");
delay(1);
Hifi_HIFI_reset_WBS_H($BBID);
Hifi_HIFI_reset_WBS_V($BBID);
delay(1);
//Switch back on HK request on WBS
Hifi_HIFI_Housekeeping_on(hk_rate,"ON","ON","ON","ON","ON","ON");
delay(1);
//
}
//HIFI-COP-1.2-FPU_FT
obs HifiEng_FPU_FT_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b","8"]; // HIFI band
double lo_freq = 500.0; //LO frequency
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(FPU_FT_COP_proc_ops(band,lo_freq,prime_or_redundant));
// 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) {
// Test execution
FPU_FT_COP_proc_ops(band,lo_freq,prime_or_redundant);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
StopMode_block_ops();
}
}
}
//Procedure to calculate individual LCU memory segments
procedure LcuChecksumRecalcSegmented_aot {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string code_category = "Safe" in ["Safe","Critical","Table","Table_all","Unused"]; //Safe, Critical, Table, Unused or Table_all
string hifi_HIF_block_when_nok = "NO" in ["YES","NO"]; // HIF_block_when_nok
}{
//Band 0 can be chosen in transition to dissipative_II
//If it is selected and test is on table, only the delay is kept
if(band == "0" && code_category == "Table") {
delay(2);
} else {
//If we are in band 0, band number has to be changed as place-holder
if(band == "0") {
band = "1a";
}
//
//Criticality keyword
string hifi_HIF_lcu_critical = "Safe";
if(code_category == "Table") {
hifi_HIF_lcu_critical = "Table";
}
if(code_category == "Critical") {
hifi_HIF_lcu_critical = "Critical";
}
//
{int,int}[] addresses = [];
int hifi_Nsteps = 48;
//Fix number of entries in addresses
//Get tupple of addresses and checksum
if(code_category == "Table") {
{{int,int}[],int,int} add_crc = LcuGetTableAddress_ops(band);
addresses = add_crc{0};
int crc_total = add_crc{1};
int length_total = add_crc{2};
}
if(code_category == "Safe" || code_category == "Critical" || code_category == "Unused") {
add_crc = LcuGetCodeAddress_ops(code_category);
addresses = add_crc{0};
crc_total = add_crc{1};
length_total = add_crc{2};
}
if(code_category == "Table_all") {
//Get start address, and length for one band
add_crc = LcuGetTableAddress_ops("1a");
int address_start = add_crc{0}[0]{0};
crc_total = add_crc{1};
length_total = 14 * add_crc{2};
addresses = add_crc{0};
addresses[0] = {address_start,length_total};
for(int j = 1 .. hifi_Nsteps - 1) {
addresses[j] = {0,0};
}
//Loop on bands for individual checksums
string[] band_array = ["1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"];
for(int i = 0 .. 12) {
add_crc = LcuGetTableAddress_ops(band_array[i]);
crc_total = crc_total + add_crc{1};
}
//Wrap-around CRC
crc_total = crc_total % (0xffff + 1);
//
}
//Send TC to ICU
Hifi_HIFI_check_LCU_memparts($BBID,hifi_HIF_lcu_critical,band,hifi_HIF_block_when_nok,crc_total,hifi_Nsteps,addresses);
//Compute total delay: proportional to size to compute
double crc_speed = 66000.0;
//in byte/sec
int checksum_total_delay = iceil(double(length_total) / crc_speed) + 1;
delay(checksum_total_delay);
//
}
}
//HIFI investigation of diplexer with M1, procedure
//Perform diplexer scans at a series of M1 values
//Frequencies and M1 values to use are pre-tabulated
procedure Diplexerscan_M1_proc_fm_TV {
string band = "7b" in ["3b","7b"]; // HIFI band
int testblock = 1 in [1,3]; //Test block for 3b
}{
mois_comment("Start of Diplexer scan investigation in band " + band);
mois_comment("For this test, a special LCU safety table should have been uploaded via dedicated TPF files");
//We will loop on tabulated frequencies
//For each we will tune LO power and do diplexer scans
//for various M1 settings for 7b, and M1/M2 combinations for 3b
//1. Get the list of frequencies to be used for the scan
string tab1 = "config_M1calib_" + band + "_TV.config";
int total = table_size(tab1);
if(band == "3b") {
string tab2 = "config_M2calib_" + band + "_TV.config";
}
double[] freq = [];
double[] m1_1 = [];
double[] m1_2 = [];
double[] m1_3 = [];
double[] m1_4 = [];
double[] m1_5 = [];
double[] m1_6 = [];
double[] m1_7 = [];
double[] m1_8 = [];
double[] m2_1 = [];
double[] m2_2 = [];
double[] m2_3 = [];
double[] m3_1 = [];
for(int j = 1 .. total) {
freq[j] = dlookup(tab1,"" + j,"frequency");
m1_1[j] = dlookup(tab1,"" + j,"m1_1");
m1_2[j] = dlookup(tab1,"" + j,"m1_2");
m1_3[j] = dlookup(tab1,"" + j,"m1_3");
m1_4[j] = dlookup(tab1,"" + j,"m1_4");
m1_5[j] = dlookup(tab1,"" + j,"m1_5");
if(band == "3b") {
m1_6[j] = dlookup(tab1,"" + j,"m1_6");
m1_7[j] = dlookup(tab1,"" + j,"m1_7");
m1_8[j] = dlookup(tab1,"" + j,"m1_8");
m2_1[j] = dlookup(tab2,"" + j,"m2_1");
m2_2[j] = dlookup(tab2,"" + j,"m2_2");
m2_3[j] = dlookup(tab2,"" + j,"m2_3");
m3_1[j] = dlookup(tab2,"" + j,"m3_1");
}
//Check whether this combination of band+freq is allowed in the current CUS
Check_Band_vs_Freq_proc_fm(band,freq[j]);
}
//
mois_step("Switch-on LO band");
//Only if first testblock
if(testblock == 1) {
LCU_switchon_proc_fm(band);
//Wait an extra delay of 10 min for mid term stabilization
delay(600);
//
}
mois_step("Loop on frequencies and multiplier settings");
//Start loop on diplexer scans
double[] m1_array = [];
double[] m2_array = [];
for(int i = 1 .. total) {
//Configure FPU at that frequency
Init_MSA_fm(band,"CLOSE",freq[i],"ON");
//
//Loop on M1 settings
int nb_m1 = 5;
int nb_m2 = 1;
if(band == "3b") {
m1_array = [m1_1[i],m1_2[i],m1_3[i],m1_4[i],m1_5[i],m1_6[i],m1_7[i],m1_8[i]];
//now work with 3 blocks of 1 M2
m2_array = [m2_1[i]];
if(testblock == 2) {
m2_array = [m2_2[i]];
}
if(testblock == 3) {
m2_array = [m2_3[i]];
}
nb_m1 = 8;
nb_m2 = 1;
//3; //now work with 3 blocks of 1 M2
}
if(band == "7b") {
m1_array = [m1_1[i],m1_2[i],m1_3[i],m1_4[i],m1_5[i]];
nb_m1 = 5;
}
//
for(int k = 0 .. nb_m1 - 1) {
//Band 7b: loop only on M1
if(band == "7b") {
//Prepare for diplexer scan
//In case of band 6 or 7, use special biases
if(band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_dipscan_h","bias_dipscan_v","bias_max_h","bias_max_v"],band,freq[1]);
//First go to 4mV
Mixerbias_block_fm(result[2]{0},result[3]{0});
//Then to 3mV
Mixerbias_block_fm(result[0]{0},result[1]{0});
}
//
//Use nominal diplexer values
double[] result_dip = Get_Diplexer_setting(band,freq[i]);
Set_Diplexer_current_block_fm(result_dip[0],result_dip[1]);
//First scan will be done at max Vd2
LCU_config_w_M1_block_fm(band,freq[i],m1_array[k]);
//Perform diplexer scan at that frequency and M1 setting
double diplexer_current_min_h = -2.24;
double diplexer_current_max_h = 2.24;
double diplexer_current_step = -0.073;
//i.e. approx 4.48/61
int n_steps = 61;
double stepTime = 0.1;
//
Scan_diplexer_block_fm(band,diplexer_current_max_h,diplexer_current_max_h,diplexer_current_step,n_steps,stepTime);
//Add delay in order to get 30 sec between first tuning macro and this scan
//delay(16); //no delay now since req is 30sec between 2 subsequent TM
Scan_diplexer_block_fm(band,diplexer_current_max_h,diplexer_current_max_h,diplexer_current_step,n_steps,stepTime);
//Back to nominal diplexer values for next tuning
result_dip = Get_Diplexer_setting(band,freq[i]);
Set_Diplexer_current_block_fm(result_dip[0],result_dip[1]);
//In case of band 6 or 7,go back to nominal bias values for next LO tuning
if(band == "7b") {
result = ConfigurationReader("name_confilfpu",["bias_max_h","bias_max_v"],band,freq[1]);
//First go to 4mV
Mixerbias_block_fm(result[0]{0},result[1]{0});
//Then to nominal
result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,freq[1]);
Mixerbias_block_fm(result[0]{0},result[1]{0});
}
//Second diplexer scan at Vd2max - 100mV, or best-guess
//Perform LO tuning at that frequency and M1 to get a reasonable pumping level
LO_tuning_w_M1_block_fm(band,freq[i],m1_array[k]);
//message(band+", "+freq[i]+", "+m1_array[k]);
//Now prepare for diplexer scan
//In case of band 6 or 7, use special biases
if(band == "7b") {
result = ConfigurationReader("name_confilfpu",["bias_dipscan_h","bias_dipscan_v","bias_max_h","bias_max_v"],band,freq[1]);
//First go to 4mV
Mixerbias_block_fm(result[2]{0},result[3]{0});
//Then to 3mV
Mixerbias_block_fm(result[0]{0},result[1]{0});
}
//
Scan_diplexer_block_fm(band,diplexer_current_max_h,diplexer_current_max_h,diplexer_current_step,n_steps,stepTime);
//
}
if(band == "3b") {
for(int l = 0 .. nb_m2 - 1) {
//Prepare for diplexer scan
//Use nominal diplexer values
result_dip = Get_Diplexer_setting(band,freq[i]);
Set_Diplexer_current_block_fm(result_dip[0],result_dip[1]);
//Set the maximum Vd2 available
LCU_config_w_M1M2M3_block_fm(band,freq[i],m1_array[k],m2_array[l],m3_1[i]);
//message(band+", "+freq[i]+", "+m1_array[k]+", "+m2_array[l]+", "+m3_1[i]);
//Perform diplexer scan at that frequency and M1 setting
diplexer_current_min_h = -2.24;
diplexer_current_max_h = 2.24;
diplexer_current_step = -0.073;
//i.e. approx 4.48/61
n_steps = 61;
stepTime = 0.1;
//
//Perform 2 diplexer scans: one immediately after, and one X sec after the tuning macro
//so that total time between tuning macros is 1min, or 30sec between tuning macro and 2nd scan
Scan_diplexer_block_fm(band,diplexer_current_max_h,diplexer_current_max_h,diplexer_current_step,n_steps,stepTime);
//
//Add delay:
//For one minute between each tuning macro: 25sec more on average
//For 30sec between tuning macro and second scan: 16sec more on average
//Req. is now: 30sec between 2 tuning macros -> 4sec
delay(4);
//Second scan
Scan_diplexer_block_fm(band,diplexer_current_max_h,diplexer_current_max_h,diplexer_current_step,n_steps,stepTime);
}
}
//
}
}
//In case of band 6 or 7,go back to nominal values at end of loop
if(band == "7b") {
result = ConfigurationReader("name_confilfpu",["bias_max_h","bias_max_v"],band,freq[1]);
//First go to 4mV
Mixerbias_block_fm(result[0]{0},result[1]{0});
//Then to nominal
result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,freq[1]);
Mixerbias_block_fm(result[0]{0},result[1]{0});
}
//
mois_comment("At the end of this test, the standard LCU safety table should be uploaded again.");
}
// Initialisation of FPU, block with both MSA in use
// Looks at the hot load !
// It is for cold context !
block Init_MSA_SKY_fm HIFI 3997 {
string band = "1a"; // HIFI band
string chop_loop = "CLOSE";
double lo_freq = 522.0; //LO frequency
string hbb_heater = "ON" in ["ON","OFF"]; //hot source on/off
}{
Start_block();
//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_confilfpu",["chop_M3"],band,0.0);
//result_d = ConfigurationReader("name_chopper",["chop_startup_cold"],
// band,0.0);
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
//if we are in OPEN loop as we want to keep 0 voltage
//Just checking we are in range.
if(chop_loop == "CLOSE") {
chopper = Check_Chopper_Prime_Redundant(chopper);
}
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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,lo_freq);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
//In case of band 6 or 7, bias have been set to 4mV. Now set to nominal
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq);
Mixerbias(result[0]{0},result[1]{0});
}
//
//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);
}
//
//Hifi_HIFI_non_periodic_hk_FCU ();
}
// Standing wave analysis
// This is the testmode to loop on all parameters for total time estimate
//HIFI-COP-3-StWv1
obs HifiManCmd_standing_wave_noretune_MOIS {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//General parameters in use
string backend = "both";
string[] hrs_mode = ["mr","mr"];
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Standing_wave_noretune_MOIS_proc_ops(band,backend,hrs_mode));
// 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) {
// Test execution
Standing_wave_noretune_MOIS_proc_ops(band,backend,hrs_mode);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
/////////////////////////////////////////
// Testmodes for handling of LCU safety
// tables and memory patches
// AdJ - 17-08-2006: initial version
// DT - 16-04-2007: reviewed for MOC
/////////////////////////////////////////
//Upload of partial LCU safety tables partial mode
//Prime/Redundant is handled with the CUS table
//Required for flight procedures as total number of command parameters
//is limited to 999
mode HifiManCmd_upload_LCU_table_flight_ops {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string section = "P" in ["P","R"];
int start = 0;
int count = 450 in [0,450];
}{
mois_comment("This procedure MUST be performed after the LCU memory patch HIF_CUPM");
string tab = "LcuSafetyTable_" + section + ".config";
int lastline = imin(table_size(tab),start + count);
int firstline = start + 1;
mois_comment("Start LCU table upload from line " + firstline + " until line " + lastline);
mois_tmcheck("Verify that parameter HL_Mode_S is set to standby.");
StartMode_block_ops();
mois_step("Perform safety table upload");
LcuSafetyTableUpload_ops(section,start,count);
StopMode_block_mois();
}
// Measurement done after HRS 0-lag freqscan, procedure
// We measure a short stability TP and a long Y-factor in fast-chop
procedure Proc_Hotcold_w_stability {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 522.0; //Operative LO freq to be tuned in GHz
int n = 100; //Number of TP measurement during stability
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total (co-added) integration time of a phase in sec.
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length for Y-factor in fastchop
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_cold_ang");
//Look at CBB
//
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
}
//Tune at user input LO frequencies.
LO_tuning_block_fm(band,lo_freq);
//
//Magnet tuning: only up to band 5 since band6-7 have no magnets
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
{double,string}[] result_d = ConfigurationReader("name_configwbs",["tune_target_magnet"],band,lo_freq);
int tune_target_magnet = iround(result_d[0]{0});
Magnet_tuning_block_fm(band,lo_freq,"HRS",tune_target_magnet);
//HRS is preferred
}
//
//WBS calibration and backend tuning
if(backend == "wbs" || backend == "both") {
WBS_tune_proc_fm(band);
}
if(backend == "hrs" || backend == "both" || backend == "hrsFast") {
HRS_tune_block_fm(band);
}
//
//
//Total power stability measurement: WBS only, 2sec. for B1-5, 1sec for B6-7 TP
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
Stability_intcold_fm(band,n,2,"wbs",hrs_mode,"tp",chop_phase);
} else {
Stability_intcold_fm(band,n,1,"wbs",hrs_mode,"tp",chop_phase);
}
//Take Y-factor during ~10 sec. on each load in fastchop
//Configure spectrometers integration: this only applies to the Y-factor fastchop
//Integ_time expected here is the TOTAL integration time with both phases + residual HRS time
int[] res = Configure_Spectrometer_fast_chop_proc_fm(band,integ_time * 2,chop_phase,hrs_mode,backend);
integ_time = iceil(chop_phase * double(res[1] * res[2]));
//debug_print("Fast chop parameters: n_wbs1 = "+res[2]+", n_hrs_trans = "+res[3]);
int n_wbs1 = res[2];
int n_hrs_trans = res[3];
//Y-factor measurement
Hot_cold(band,hrs_mode,backend,integ_time,"fastchop",n_wbs1,n_hrs_trans);
//
}
//Check consistency between frequency and M1 choice for 7b
bool procedure Check_M1_vs_Freq_proc_fm {
string band = "7b" in ["7b","7b"]; // HIFI band
double lo_freq = 1800.0; //LO frequency
double m1 = -6.0; //M1 multiplier voltage
}{
bool go_ahead_m1 = true;
string name_configlcu = "name_configlcu_b";
{double,string}[] result = ConfigurationReader(name_configlcu,["m1_v"],band,lo_freq);
double m1_v = result[0]{0};
if(m1 > m1_v || m1 < -8.5) {
go_ahead_m1 = false;
}
if(go_ahead_m1 == false) {
error("M1 not within allowed range (-8.5 to " + m1_v + " V) for band " + band);
}
return go_ahead_m1;
}
// FPU Standby with HBB ON, block
block Band0_hbb_on_block_ops HIFI 7298 {
string band = "0"; // HIFI band
string chop_loop = "CLOSE"; // Chopper Loop status
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//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,0.0);
int band_nb = iround(result_d[0]{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,0.0);
//
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";
//
result_d = ConfigurationReader("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2","chop_g3","chop_p3","calibrator_current_on"],band,0.0);
//
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};
//
result_d = ConfigurationReader("name_confilfpu",["bias_standby_h","diplexer_standby_h","bias_standby_v","diplexer_standby_v","diplex_h_ctrl_mode","diplex_v_ctrl_mode","chop_M3right"],band,0.0);
//
double bias_H = result_d[0]{0};
double diplex_H = result_d[1]{0};
double bias_V = result_d[2]{0};
double diplex_V = result_d[3]{0};
int diplex_h_ctrl_mode = iround(result_d[4]{0});
int diplex_v_ctrl_mode = iround(result_d[5]{0});
double chopper = result_d[6]{0};
//
//Retrieve magnets.
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
result_d = ConfigurationReader("name_confilfpu",["magnet_standby_h","magnet_standby_v"],band,0.0);
double magnetcurrent_H = result_d[0]{0};
double magnetcurrent_V = result_d[1]{0};
}
//
//Upconverter: should be kept ON at this stage. No particular action.
//
if(prime_or_redundant == "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);
}
//
result_d = ConfigurationReader("name_delays",["config_fpu_delay"],band,0.0);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
Hifi_HIFI_non_periodic_hk_FCU();
//
mois_tmcheck("Check that parameter HF_APR_CS_C is set to " + calibcurrent + " mA");
mois_tmcheck("Check that parameter HF_DPR_CHLOOP_S is set to " + chop_loop);
mois_tmcheck("Check that parameter HF_DPR_CHSINE_S is set to " + chop_sine_s);
}
block WBS_Multi_Comb HIFI 3965 {
string band = "4a"; // HIFI band (needed to estimate stabilization)
double lo_freq = 978200.0; // LO frequency
int nb_comb = 10; //The number of COMBs to integrate in a row
}{
// 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});
//
// Other standard parameters
result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s","hwv_laser1_s","hwv_laser2_s","hwv_heater","hwv_latchup_s"],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};
string hwv_laser1_s = result_d[4]{1};
string hwv_laser2_s = result_d[5]{1};
int hwv_heater = iround(result_d[6]{0});
string hwv_latchup_s = result_d[7]{1};
// Delay for configure
result_d = ConfigurationReader("name_delays",["wbs_config_delay"],band,0.0);
int wbs_config_delay = iround(result_d[0]{0});
//
// Commands without science data
// Switches (2s total)
Hifi_HIFI_Single_cmd($BBID,"HWH_ZERO_ON");
Hifi_HIFI_Single_cmd($BBID,"HWV_ZERO_ON");
delay(1);
Hifi_HIFI_Single_cmd($BBID,"HWH_COMB_ON");
Hifi_HIFI_Single_cmd($BBID,"HWV_COMB_ON");
delay(1);
// Attenuators
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
//
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
// Integration (science data in procedure)
DoCont2sIntegration(band,lo_freq,nb_comb);
// Back to normal (2s)
Hifi_HIFI_Single_cmd($BBID,"HWH_COMB_OFF");
Hifi_HIFI_Single_cmd($BBID,"HWV_COMB_OFF");
delay(1);
Hifi_HIFI_Single_cmd($BBID,"HWH_ZERO_OFF");
Hifi_HIFI_Single_cmd($BBID,"HWV_ZERO_OFF");
delay(1);
//
// no additional delay for packet transmission needed
}
//Notify PDU status ON, block
//I assume all S/S are present
block HIFI_notify_PDU_status_on_block_ops HIFI 7655 {
string status_FCU = "ON" in ["ON","OFF"]; //Status of FCU
string status_LCU = "ON" in ["ON","OFF"]; //Status of LCU
string status_WBSV = "ON" in ["ON","OFF"]; //Status of WBSV
string status_WBSH = "ON" in ["ON","OFF"]; //Status of WBSH
string status_HRSV = "ON" in ["ON","OFF"]; //Status of HRSV
string status_HRSH = "ON" in ["ON","OFF"]; //Status of HRSH
string apply_to_subsystem = "FCU" in ["FCU","LCU","WBSH","WBSV","HRSH","HRSV","ALL"];
}{
StartBlock_ops();
//This has no delay
Hifi_HIFI_notify_PDU_status(status_FCU,status_LCU,status_WBSV,status_WBSH,status_HRSV,status_HRSH);
delay(1);
//Prepare message for operator: we will check whether one particular HK is ON
if(status_FCU == "ON") {
string subsyst_on = "HI_FCU_S";
}
if(status_WBSH == "ON") {
subsyst_on = "HI_WBSH_S";
}
if(status_WBSV == "ON") {
subsyst_on = "HI_WBSV_S";
}
if(status_HRSH == "ON") {
subsyst_on = "HI_HRSH_S";
}
if(status_HRSV == "ON") {
subsyst_on = "HI_HRSV_S";
}
if(status_LCU == "ON") {
subsyst_on = "HI_LCU_S";
}
mois_tmcheck("Check that the HK parameter " + subsyst_on + " is ON.");
//Specific S/S check after switch on
if(apply_to_subsystem == "FCU" || apply_to_subsystem == "ALL") {
//Nothing in particular
}
if(apply_to_subsystem == "WBSH" || apply_to_subsystem == "ALL") {
//This is now done at end of procedure as instrument mode status check
//mois_tmcheck("Check that both parameters HWH_Laser1_S and HWH_Laser2_S are OFF");
//mois_tmcheck("Check that parameter HWH_Zero_S is ON");
//mois_tmcheck("Check that parameter HWH_IN_ATT is set to 15, and parameters HWH_Band_1_ATT, HWH_Band_2_ATT, HWH_Band_3_ATT, HWH_Band_4_ATT are set to 7");
}
if(apply_to_subsystem == "WBSV" || apply_to_subsystem == "ALL") {
//This is now done at end of procedure as instrument mode status check
//mois_tmcheck("Check that both parameters HWV_Laser1_S and HWV_Laser2_S are OFF");
//mois_tmcheck("Check that parameter HWV_Zero_S is ON");
//mois_tmcheck("Check that parameter HWV_IN_ATT is set to 15, and parameters HWV_Band_1_ATT, HWV_Band_2_ATT, HWV_Band_3_ATT, HWV_Band_4_ATT are set to 7");
}
if(apply_to_subsystem == "HRSH" || apply_to_subsystem == "ALL") {
//This is now done at end of procedure as instrument mode status check
//mois_tmcheck("Check that parameters HRH_1U_ATT, HRH_1L_ATT, HRH_2U_ATT, HRH_2L_ATT, HRH_3U_ATT, HRH_3L_ATT, HRH_4U_ATT and HRH_4L_ATT are set to 15.5");
}
if(apply_to_subsystem == "HRSV" || apply_to_subsystem == "ALL") {
//This is now done at end of procedure as instrument mode status check
//mois_tmcheck("Check that parameters HRV_1U_ATT, HRV_1L_ATT, HRV_2U_ATT, HRV_2L_ATT, HRV_3U_ATT, HRV_3L_ATT, HRV_4U_ATT and HRV_4L_ATT are set to 15.5");
}
if(apply_to_subsystem == "LCU" || apply_to_subsystem == "ALL") {
//This is now done at end of procedure as instrument mode status check
//mois_tmcheck("Check that parameter HL_MODE_S is standby");
//mois_tmcheck("Check that parameter HL_Channel_S is OFF");
}
}
//General script to read TM1, TM2,etc, block
block LCU_Read_TM_pages_OLD_block_fm HIFI 3968 {
}{
//Re-implement old way to be consistent with MOIS manual procedures
//
//Page 7AH dump: will be introduced in the MOIS - 2 sec delays
Hifi_HIFI_LCU_read_settings();
delay(2);
/////////////////////////////////////
//Temporary work-around for TVTB SFT
//Get various TM pages
Hifi_HIFI_LCU_macro_tuning_hk("HSK_TM1");
delay(2);
Hifi_HIFI_LCU_macro_tuning_hk("HSK_TM2");
delay(2);
Hifi_HIFI_LCU_macro_tuning_hk("HSK_TM3");
delay(2);
Hifi_HIFI_LCU_macro_tuning_hk("HSK_TM");
delay(2);
Hifi_HIFI_LCU_macro_tuning_hk("HSK_G");
delay(2);
//
//Clear error flags
Hifi_HIFI_LCU_Single($BBID,"HL_CLR_ERR");
//
}
// 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;
}
//Set LCU2a back to standby status, procedure
procedure LCU2a_standby_proc_fm {
string band = "2a"; // HIFI band
double lo_freq = 700.0 in [647.0,710.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
///////////////////////////////////////////////////
// CUS scripts thermal monitoring of the FPU.
// Based on SCOE tests initially performed for
// the QM by BK.
// They are here updated for FM. There will be
// independent tests for respective H and V.
//
// DT - 17/11/04: first draft for FM. Thermal test
// new has been removed.
//
///////////////////////////////////////////////////
//modes: see fm_testmodes.cus
/////////////////////////////////////////////
// Blocks for thermal tests
/////////////////////////////////////////////
// thermal tests
block Thermal_fm HIFI 3280 {
string band = "1a"; // HIFI band
double lo_freq = 522.0; //LO frequency
}{
//Start_block();
//Get band number
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["band"],band,lo_freq);
int band_nb = iround(result_d[0]{0});
//
//Get Targetted values for magnet, mixer bias, heater time and diplexer
double[] cresult_d = CalibrationReader("name_configthermal",["dipl_h","magn_h","mbias_h","heat_h","dipl_v","magn_v","mbias_v","heat_v"],band,0.0);
double target_dipl_h = cresult_d[0];
double target_magn_h = cresult_d[1];
double target_mbias_h = cresult_d[2];
double target_heat_h = cresult_d[3];
double target_dipl_v = cresult_d[4];
double target_magn_v = cresult_d[5];
double target_mbias_v = cresult_d[6];
double target_heat_v = cresult_d[7];
//
int diplex_h_ctrl_mode = 0;
//
//IF amplifiers should be set to standby values
result_d = ConfigurationReader("name_confilfpu",["fif1v_h","fif1c_h","fif2v_h","fif2c_h"],"0",0.0);
double volt_H_FIF_1 = result_d[0]{0};
double curr_H_FIF_1 = result_d[1]{0};
double volt_H_FIF_2 = result_d[2]{0};
double curr_H_FIF_2 = result_d[3]{0};
//
result_d = ConfigurationReader("name_confilfpu",["sif1v_h","sif1c_h","sif2v_h","sif2c_h","sif3v_h","sif3c_h"],"0",0.0);
double volt_H_SIF_1 = result_d[0]{0};
double curr_H_SIF_1 = result_d[1]{0};
double volt_H_SIF_2 = result_d[2]{0};
double curr_H_SIF_2 = result_d[3]{0};
double volt_H_SIF_3 = result_d[4]{0};
double curr_H_SIF_3 = result_d[5]{0};
//
int diplex_v_ctrl_mode = 0;
//
result_d = ConfigurationReader("name_confilfpu",["fif1v_v","fif1c_v","fif2v_v","fif2c_v"],"0",0.0);
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};
//
result_d = ConfigurationReader("name_confilfpu",["sif1v_v","sif1c_v","sif2v_v","sif2c_v","sif3v_v","sif3c_v"],"0",0.0);
double volt_V_SIF_1 = result_d[0]{0};
double curr_V_SIF_1 = result_d[1]{0};
double volt_V_SIF_2 = result_d[2]{0};
double curr_V_SIF_2 = result_d[3]{0};
double volt_V_SIF_3 = result_d[4]{0};
double curr_V_SIF_3 = result_d[5]{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"],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});
//
//
//
result_d = ConfigurationReader("name_confilfpu",["calibrator_current_on"],band,lo_freq);
double calibcurrent = result_d[0]{0};
//Initialize settings
double bias_H = 0.0;
double magnetcurrent_H = 0.0;
double diplex_H = 0.0;
double bias_V = 0.0;
double magnetcurrent_V = 0.0;
double diplex_V = 0.0;
//Look at CBB at start of test
result_d = ConfigurationReader("name_confilfpu",["chop_cold"],band,lo_freq);
double chopper = result_d[0]{0};
chopper = Check_Chopper_Prime_Redundant(chopper);
//
//Start modification of FPU parameters - This is also the 0 of the test clock
//1. Initial configuration with the chopper moving to M3 middle
// and diplexer_H set to targetted value
//
//Diplexer is only used 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 {
diplex_H = target_dipl_h * 1.0;
diplex_V = target_dipl_v * 0.0;
//
HIFI_Configure_FCU_proc_fm(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);
//
delay(900);
//
//Actuate diplexer_V
diplex_H = target_dipl_h * 1.0;
diplex_V = target_dipl_v * 1.0;
//
HIFI_Configure_FCU_proc_fm(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);
//
delay(900);
}
//
//2. Set IF1 ON
//
result_d = ConfigurationReader("name_confilfpu",["fif1v_h","fif1c_h","fif2v_h","fif2c_h"],band,lo_freq);
volt_H_FIF_1 = result_d[0]{0};
curr_H_FIF_1 = result_d[1]{0};
volt_H_FIF_2 = result_d[2]{0};
curr_H_FIF_2 = result_d[3]{0};
//
HIFI_Configure_FCU_proc_fm(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);
delay(900);
//
result_d = ConfigurationReader("name_confilfpu",["fif1v_v","fif1c_v","fif2v_v","fif2c_v"],band,lo_freq);
volt_V_FIF_1 = result_d[0]{0};
curr_V_FIF_1 = result_d[1]{0};
volt_V_FIF_2 = result_d[2]{0};
curr_V_FIF_2 = result_d[3]{0};
//
HIFI_Configure_FCU_proc_fm(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);
delay(900);
//
//3. Set IF2 ON
//
result_d = ConfigurationReader("name_confilfpu",["sif1v_h","sif1c_h","sif2v_h","sif2c_h","sif3v_h","sif3c_h"],band,lo_freq);
volt_H_SIF_1 = result_d[0]{0};
curr_H_SIF_1 = result_d[1]{0};
volt_H_SIF_2 = result_d[2]{0};
curr_H_SIF_2 = result_d[3]{0};
volt_H_SIF_3 = result_d[4]{0};
curr_H_SIF_3 = result_d[5]{0};
//
HIFI_Configure_FCU_proc_fm(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);
delay(900);
//
result_d = ConfigurationReader("name_confilfpu",["sif1v_v","sif1c_v","sif2v_v","sif2c_v","sif3v_v","sif3c_v"],band,lo_freq);
volt_V_SIF_1 = result_d[0]{0};
curr_V_SIF_1 = result_d[1]{0};
volt_V_SIF_2 = result_d[2]{0};
curr_V_SIF_2 = result_d[3]{0};
volt_V_SIF_3 = result_d[4]{0};
curr_V_SIF_3 = result_d[5]{0};
//
HIFI_Configure_FCU_proc_fm(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);
delay(900);
//
//5. Magnet current to max., then to dedicated value for thermal test
if(band_nb <= 5) {
//Set to targetted values
magnetcurrent_H = target_magn_h;
//
//Magnet-H
HIFI_Configure_FCU_proc_fm(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);
delay(900);
magnetcurrent_V = target_magn_v;
//
//Magnet-V
HIFI_Configure_FCU_proc_fm(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);
delay(900);
}
//
//6. Bias voltage to dedicated value for thermal test
bias_H = target_mbias_h;
//H-bias
HIFI_Configure_FCU_proc_fm(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);
delay(900);
//V-bias
bias_V = target_mbias_v;
HIFI_Configure_FCU_proc_fm(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);
delay(900);
//
//7.Turn everything off
bias_H = 0.0;
bias_V = 0.0;
magnetcurrent_H = 0.0;
magnetcurrent_V = 0.0;
diplex_H = 0.0;
diplex_V = 0.0;
//
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"],"0",0.0);
//
volt_H_FIF_1 = result_d[1]{0};
curr_H_FIF_1 = result_d[2]{0};
volt_H_FIF_2 = result_d[3]{0};
curr_H_FIF_2 = result_d[4]{0};
volt_H_SIF_1 = result_d[5]{0};
curr_H_SIF_1 = result_d[6]{0};
volt_H_SIF_2 = result_d[7]{0};
curr_H_SIF_2 = result_d[8]{0};
volt_H_SIF_3 = result_d[9]{0};
curr_H_SIF_3 = result_d[10]{0};
//
{double,string}[] result_d2 = ConfigurationReader("name_confilfpu",["fif1v_v","fif1c_v","fif2v_v","fif2c_v","sif1v_v","sif1c_v","sif2v_v","sif2c_v","sif3v_v","sif3c_v"],"0",0.0);
//
volt_V_FIF_1 = result_d2[0]{0};
curr_V_FIF_1 = result_d2[1]{0};
volt_V_FIF_2 = result_d2[2]{0};
curr_V_FIF_2 = result_d2[3]{0};
//
volt_V_SIF_1 = result_d2[4]{0};
curr_V_SIF_1 = result_d2[5]{0};
volt_V_SIF_2 = result_d2[6]{0};
curr_V_SIF_2 = result_d2[7]{0};
volt_V_SIF_3 = result_d2[8]{0};
curr_V_SIF_3 = result_d2[9]{0};
//
HIFI_Configure_FCU_proc_fm(0,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);
delay(1200);
//
//12. Check heater current effect on temperature: Let current ON
// during the standard deflux time.
//First, call same FPU configuration, but specify band to be used to switch on band again
//We will bias the junction to check when
//the heater effect is effective
result_d = ConfigurationReader("name_confilfpu",["bias_very_low_h","bias_very_low_v"],band,lo_freq);
bias_H = result_d[0]{0};
bias_V = result_d[1]{0};
//
HIFI_Configure_FCU_proc_fm(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);
delay(3);
//
//Get time during which one wants to send the pulse
double max_heater_time_h = target_heat_h * 1000.0;
//in msec
double max_heater_time_v = target_heat_v * 1000.0;
//in msec
//Start to send the pulse
//H-heater
Hifi_HIFI_HF_CH1_DHTR_C($BBID,max_heater_time_h);
//delay(iceil(max_heater_time_h / 1000.0) + 1);
delay(600);
//V-heater
Hifi_HIFI_HF_CV1_DHTR_C($BBID,max_heater_time_v);
//delay(iceil(max_heater_time_v / 1000.0) + 1);
delay(1200);
//
//13. Chop to HBB
result_d = ConfigurationReader("name_confilfpu",["chop_hot"],band,lo_freq);
chopper = result_d[0]{0};
chopper = Check_Chopper_Prime_Redundant(chopper);
//
HIFI_Configure_FCU_proc_fm(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);
delay(600);
//14. Chop back to CBB
result_d = ConfigurationReader("name_confilfpu",["chop_cold"],band,lo_freq);
chopper = result_d[0]{0};
chopper = Check_Chopper_Prime_Redundant(chopper);
//
HIFI_Configure_FCU_proc_fm(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);
delay(600);
//
}
// Global frequency switch spectroscopy for stability measurement, procedure
// We assume it works like fast chop
procedure Freqswitch_spectro_for_Stability_proc_fm {
string band = "1a"; // HIFI band
int n = 100; //The number of integration pairs
int integ_time = 8; //Total (co-added) integration time of a phase in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
}{
//First derive backend setting codes as expected by VO's routine
//Build up backend parameter tupple:
{{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = BackendSettings(band,0.0,hrs_mode,backend);
// Readout parameters for HRS1,HRS2, WBS1,WBS2
//Compute data_time and n_switch using the wrapper
int[] res = ConfigSlowChop(integ_time,"fs",band,0.0,backendreadoutparms);
int data_time = res[0];
int n_switch = n * res[1];
//For stability measurement, the number of loop is a user input
// Now call the spectroscopy setup: it is common to ILT and AOT CUS.
// The deadtimes output is not used at ILT level.
{double,double} dtimes = ConfigSpectroscopySlowChop(data_time,n_switch,"fs",band,0.0,backendreadoutparms,true);
//Compute data-rates
{int,double[]} dataparms = DataTaking(backendreadoutparms,data_time);
double[] rates = dataparms{1};
// set data rates
non_ess_hk_data_rate(rates[2] / 1024.0);
data_rate(rates[0] / 1024.0);
//Now start the long integration
Hifi_HIFI_Spectr_freq_switch($BBID);
//
Apply_Slow_Chop_delay(data_time * n_switch,band,backend);
// 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 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);
// Combined sideband scaling
double[] gssb = InterpolateGssb(band,reffreq);
double avgainfac = 0.5 / gssb[0] + 0.5 / gssb[1];
double rescalefac = gssb[1] * avgainfac;
// Correct for multiple frequencies
double multiplier = sqrt(1.0 / double(nfreq));
noisevalues{0} = noisevalues{0} * gssb[0] * multiplier;
noisevalues{1} = noisevalues{1} * gssb[0] * 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 decnoise_lores = noisevalues{0} / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]);
double decnoise_hires = noisevalues{1} / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]);
double indnoise_lores = noisevalues{2} * rescalefac;
double indnoise_hires = noisevalues{3} * rescalefac;
} else {
// Get single sideband noise equivalent
decnoise_lores = noisevalues{0} * avgainfac;
decnoise_hires = noisevalues{1} * avgainfac;
indnoise_lores = noisevalues{2} * rescalefac;
indnoise_hires = noisevalues{3} * rescalefac;
}
// Return noise values and the maximum ratio of drift to radiometric noise
return {decnoise_lores,decnoise_hires,indnoise_lores,indnoise_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);
// 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;
int ihold = 0;
// Do I have to make loads in short nods and subsequent holds?
if(iscross) {
bool holdforload = n_pointsperscan > 1;
int phaseshift = 0;
} else {
holdforload = n_pointsperscan == 1 && n_loadinterval > n_cycles;
phaseshift = 1;
}
bool isOffAtPoint = false;
bool isLastPhase = false;
////////////////////////////////////////////////////////////////////////
// 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;
iphase = iphase + 1;
}
//////////////////////////////////////////////////////////////////////
// States for actual observations
if(state[0] == 3) {
// First nodding position
// Sanity check
if(runintostate && iscross) {
CError("Ongoing integration while arriving at ON nodding position.");
}
// Check whether we are in a cross mode using computed OFF
isOffAtPoint = iscross && holdforload && inod % 2 == 1;
// Configure measurement
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) {
if(isOffAtPoint) {
HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates);
} else {
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
if(isOffAtPoint) {
HIFIFastChopOffIntegration(data_time,n_seq,band,lo_freq,choppars,rates);
} else {
HIFIFastChopOnIntegration(data_time,n_seq,band,lo_freq,choppars,rates);
}
// Final point before nod
// Dirty trick to find out whether we are at the very last point
isLastPhase = telescopetimes[0] + tinitslew - (time() - startobs) < data_time * n_seq;
if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) {
inod = inod + 1;
}
// 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 == phaseshift) {
ihold = ihold + 1;
if(holdforload && ihold % n_loadinterval == 0 && n_load == 0 && !isLastPhase) {
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 measurement between two A-A or B-B phases if required
// Time partially included in pointing
if(n_load > 0) {
delay(readoutdead);
LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms);
// Run into final hold for very last point
if(isLastPhase) {
runintostate = true;
}
}
}
// Update phase counter
iphase = iphase + 1;
}
// Second pointing phase
if(state[0] == 7) {
// second nod position
// Sanity check
if(runintostate && iscross) {
CError("Ongoing integration while arriving at OFF nodding 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);
// Final point before nod
// Dirty trick to find out whether we are at the very last point
isLastPhase = telescopetimes[0] + tinitslew - (time() - startobs) < data_time * n_seq;
if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == 1) {
inod = inod + 1;
}
// Special treatment for all cases where load has to be replaced by hold:
if(iphase % n_pointsperscan == 0 && iphase / n_pointsperscan % 2 == phaseshift) {
ihold = ihold + 1;
if(holdforload && ihold % n_loadinterval == 0 && n_load == 0 && !isLastPhase) {
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 measurement between two A-A or B-B phases if required
// Time partially included in pointing
if(n_load > 0) {
delay(readoutdead);
LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms);
// Run into final hold for very last point
if(isLastPhase) {
runintostate = true;
}
}
}
// Update phase counter
iphase = iphase + 1;
}
// Load nod
if(state[0] == 9) {
// Load nod
// Sanity check
if(runintostate) {
CError("Ongoing integration while starting load calibration slew.");
}
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) {
if(!runintostate) {
delay(readoutdead);
}
if(final_load) {
// Perform final load measurement
LoadMeasurement(band,lo_freq,eff_resolution{0},load_datatime,backendreadoutparms);
}
runintostate = false;
HIFICloseObs();
}
}
}
// FPU settling time for a mixer band change, 2nd block
// Block for second tuning
block FPU_Settling_time_second_tuning_fm HIFI 3684 {
string band_2 = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
int int_time2 = 600; //Integration time after first and second switch
double lo_freq_2 = 500.0; //LO frequency in sub-band b
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//
//
//Init and tune of LO: configuration from safe to tuned.
LCU_config_nominal_proc_fm(band_2,lo_freq_2);
LO_tuning_w_mixerchoice_proc(band_2,lo_freq_2,"H");
//
//Configure spectroscopy integration
Configure_Spectrometer_proc_fm(band_2,int_time2,["wb1","wb1"],backend);
//4 sec. integration
//Take series of spectra during int_time2 seconds
HIFI_Spectr_total_power_proc_fm(band_2,backend,int_time2);
//
//Now switch off LO sub-band
LCU_switch_off_proc_fm();
}
////////////////////////////////////////////////////////////////////////////
// Procedure to generate the instrument commands for the observing mode
procedure EngSScanDBS_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}
double[] freqgrid = [978053.7,978301.8,978381.1]; // Table of frequency points
bool retunediplexer = false; // need for diplexer retuning
bool retunelo = false; // whether to retune LO Vd2 with freq
int data_time = 4; // chunk size
int n_chop = 1; // Normal number of chop cycles per frequency and pointing
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 shiftlength = 10; // Shift of the loop start relative to the pointing
int startobs = 0; // Actual starting time of observation
int[] telescopetimes = [300,180,20,1,21,0]; // Timing of the observation from telescope
}{
// 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
// 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 tune duration for initial load measurement
int bigtunestep = duration(HIFIChangeLO(band,freqgrid[0],reffreq,retunediplexer,retunelo));
int n_loadinterval = n_cycles;
// 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_freq = 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:
// Start with setup at reference frequency, go to grid in the next step
//
HIFIInitObs();
TuneHIFI(band,reffreq,hrs1,hrs2,wbs1{0},wbs2{0},"sscan_normal");
// First load measurement
HIFISetHK("normal",false);
SScanLoadMeasurement(band,reffreq,reffreq,true,eff_resolution{0},data_time,backendreadoutparms);
delay(tinitslew - (time() - startobs) - bigtunestep + shiftlength - hkduration);
//
// Now switch to the actual frequency grid to be measured
double runningfreq = freqgrid[i_freq];
HIFIChangeLO(band,runningfreq,reffreq,retunediplexer,retunelo);
runintostate = true;
}
//////////////////////////////////////////////////////////////////////
// States for actual observations
if(state[0] == 3) {
// First nodding position
// state counters
runintostate = false;
i_phase = (state[2] + 1) % 2;
// intermediate nod cycles without retuning
// (Check for match with first or last cycle index)
if(n_cycles > 1 && state[2] % n_cycles != state[2] % 2) {
delay(shiftlength);
}
// Actual integration
HIFIConfigureSlowChopIntegration(data_time,n_chop,band,reffreq,backendreadoutparms);
HIFISlowChopOnIntegration(data_time,n_chop,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_freq = i_freq + 1;
runningfreq = freqgrid[i_freq];
HIFIChangeLO(band,runningfreq,reffreq,retunediplexer,retunelo);
runintostate = true;
}
}
// Active Backend HK if we have a nod slew without calibration
if(i_phase == 0 && state[2] % n_loadinterval > 0) {
HIFIActiveHK("normal",tnodslew);
}
}
if(state[0] == 7) {
// Second nodding position
// state counters
runintostate = false;
i_phase = state[2] % 2;
// intermediate nod cycles without retuning
if(n_cycles > 1 && state[2] % n_cycles != (state[2] + 1) % 2) {
delay(shiftlength);
}
// Actual integration
HIFIConfigureSlowChopIntegration(data_time,n_chop,band,reffreq,backendreadoutparms);
HIFISlowChopOffIntegration(data_time,n_chop,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_freq = i_freq + 1;
runningfreq = freqgrid[i_freq];
HIFIChangeLO(band,runningfreq,reffreq,retunediplexer,retunelo);
runintostate = true;
}
}
// Active Backend HK if we have a nod slew without calibration
if(i_phase == 0 && state[2] % n_loadinterval > 0) {
HIFIActiveHK("normal",tnodslew);
}
}
if(state[0] == 9) {
// Load nod
delay(readoutdead);
SScanLoadMeasurement(band,runningfreq,reffreq,false,eff_resolution{0},data_time,backendreadoutparms);
runintostate = false;
}
if(state[0] == 5) {
// The instrument stops shiftlength before the telescope
// but I have to wait to close the observation
HIFICloseObs();
}
}
}
//General LO configuration command
block HIFI_Configure_LCU_dissipative_block_aot HIFI 6717 {
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_safe_LCU_ch5a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum);
}
if(band == "5b") {
//Band 5b
Hifi_HIFI_Conf_safe_LCU_ch5b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum);
}
if(band == "6a") {
//Band 6a
Hifi_HIFI_Conf_safe_LCU_ch6a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum);
}
if(band == "6b") {
//Band 6b
Hifi_HIFI_Conf_safe_LCU_ch6b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum);
}
if(band == "7a") {
//Band 7a
Hifi_HIFI_Conf_safe_LCU_ch7a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum);
}
if(band == "7b") {
//Band 7b
Hifi_HIFI_Conf_safe_LCU_ch7b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,drain2_v,curlim2_v,macro_checksum);
}
//
delay(config_lo_delay);
//
//Read TM pages and clear error flags
LCU_Read_TM_pages_proc_aot();
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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,"lchop");
int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0);
// 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);
// Additional constraint of compatibility of group size with load period
int loadperiod = LoadPeriod(band,reffreq,effResolution{1});
// 80% margin
int periodlimit = loadperiod * 4 / 5;
// elements of cycle - compute cycle duration
int tunedelay = LOSettlingTime(band,reffreq / 1000.0,false,true);
int load_datatime = iceil(retvalues[0]{1});
int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,effResolution{0},load_datatime,backendreadoutparms));
int perfreqtime = 2 * load_datatime + tunedelay;
int cycle = perfreqtime * n_freq_point_guess + loadlength;
if(cycle > periodlimit) {
n_freq_point_guess = imax((periodlimit - loadlength) / perfreqtime,1);
}
int n_freq_point_range = 1 - n_freq_point_guess;
if(n_freq_point_range == 0) {
n_freq_point_range = 1;
}
retvalues[1] = {"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)};
return retvalues;
}
////////////////////////////////////////////////////////////////////////
// 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;
}
//TM check when rescue mode: very difficult to identify as such.
//Is based on the reception/non-reception of certain event packets
procedure Mode_status_check_rescue {
string context = "normal" in ["normal","failure"]; //indicate if this is a normal or failure arrival to rescue
}{
mois_comment("Checking instrument status in rescue mode");
if(context == "failure") {
mois_tmcheck("Check that the previous execution of either of the telecommands: Hifi_HIFI_force_bootdefault or Hifi_HIFI_force_bootpartition, has resulted in either of the following: no (5,1) packet was received, or a (5,4) packet was received.");
}
if(context == "normal") {
mois_tmcheck("The ICU should be powered ON");
}
}
// Spectrometer configuration for fast chop, low level procedure
int[] procedure Configure_Spectrometer_fast_chop_proc_fm {
string band = "1a"; // HIFI band
int integ_time = 8; //Total integation time of the two phases in seconds
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length for fast chop
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,wb5
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//First derive backend setting codes as expected by VO's routine
//Build up backend parameter tupple:
{{bool,int,bool[]},{bool,int,bool[]},{bool,int[][]},{bool,int[][]}} backendreadoutparms = BackendSettings(band,0.0,hrs_mode,backend);
// Readout parameters for HRS1,HRS2, WBS1,WBS2
//Compute data_time and n_switch using the wrapper
int[] res = ConfigFastChop(integ_time,chop_phase,band,0.0,backendreadoutparms);
int data_time = res[0];
int n_data = res[1];
int n_chop = res[2];
// Now call the spectroscopy setup: it is common to ILT and AOT CUS.
// The deadtimes output is not used at ILT level.
{{double,double,double},{int,int}} pars = ConfigSpectroscopyFastChop_IST(chop_phase,n_chop,n_data,band,0.0,backendreadoutparms);
//
int[] final_res = [res[0],res[1],pars{1}{0},pars{1}{1}];
return final_res;
}
//Activate checksum verification in MTL
obs HifiEng_CRC_FDIR_enable_MTL {
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Enable_CRC_FDIR_block_mois());
// 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("slow",true);
//Better to set 1/10sec here
}
if(state[0] == 3) {
// Test execution
Enable_CRC_FDIR_block_mois();
}
if(state[0] == 5) {
//HIFISetHK("normal",true); // -> superfluous
HIFICloseObs();
}
}
}
// BLOCK : Functional Test No 2 (HRS Square S Internal Test)
block HRS_functional_test_No_2_Square_s_block_fm HIFI 3621 {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total integration time in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//Fill in block parameter names for each mode - consequence of SPR-0198
string[] hrs_blocks_square_s_ultra = ["square_s_ultra","square_s_ultra","square_s_ultra","square_s_ultra","square_s_ultra","square_s_ultra","square_s_ultra","square_s_ultra"];
string[] hrs_blocks_square_s_wide = ["square_s_wide","square_s_wide","square_s_wide","square_s_wide","square_s_wide","square_s_wide","square_s_wide","square_s_wide"];
string[] hrs_blocks_square_s_low = ["square_s_hilonom","low","square_s_low","low_nominal","square_s_low_nom","low","square_s_low","high_nominal_low"];
string[] hrs_blocks_square_s_nom = ["square_s_hilonom","high_nominal","high_nominal","low_nominal","square_s_low_nom","high_nominal","high_nominal","high_nominal_low"];
string[] hrs_blocks_square_s_high = ["square_s_hilonom","high_nominal","high_nominal","high","high","high_nominal","high_nominal","high_nominal_low"];
// Configure spectroscopy
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
// Configure LO and attenuators
//=============================
HRS_config_att_lo_fm(band,hrs_mode);
//
// Loops on the different configurations of the HRS
//======================================
//Calls the 5 modes to be checked
//Square_S_ultra
Hifi_HIFI_Config_HRS_H_blocks($BBID,hrs_blocks_square_s_ultra[0],hrs_blocks_square_s_ultra[1],hrs_blocks_square_s_ultra[2],hrs_blocks_square_s_ultra[3],hrs_blocks_square_s_ultra[4],hrs_blocks_square_s_ultra[5],hrs_blocks_square_s_ultra[6],hrs_blocks_square_s_ultra[7]);
//delay(1);
Hifi_HIFI_Config_HRS_V_blocks($BBID,hrs_blocks_square_s_ultra[0],hrs_blocks_square_s_ultra[1],hrs_blocks_square_s_ultra[2],hrs_blocks_square_s_ultra[3],hrs_blocks_square_s_ultra[4],hrs_blocks_square_s_ultra[5],hrs_blocks_square_s_ultra[6],hrs_blocks_square_s_ultra[7]);
delay(1);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//Square_S_wide
Hifi_HIFI_Config_HRS_H_blocks($BBID,hrs_blocks_square_s_wide[0],hrs_blocks_square_s_wide[1],hrs_blocks_square_s_wide[2],hrs_blocks_square_s_wide[3],hrs_blocks_square_s_wide[4],hrs_blocks_square_s_wide[5],hrs_blocks_square_s_wide[6],hrs_blocks_square_s_wide[7]);
//delay(1);
Hifi_HIFI_Config_HRS_V_blocks($BBID,hrs_blocks_square_s_wide[0],hrs_blocks_square_s_wide[1],hrs_blocks_square_s_wide[2],hrs_blocks_square_s_wide[3],hrs_blocks_square_s_wide[4],hrs_blocks_square_s_wide[5],hrs_blocks_square_s_wide[6],hrs_blocks_square_s_wide[7]);
delay(1);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//Square_S_low
Hifi_HIFI_Config_HRS_H_blocks($BBID,hrs_blocks_square_s_low[0],hrs_blocks_square_s_low[1],hrs_blocks_square_s_low[2],hrs_blocks_square_s_low[3],hrs_blocks_square_s_low[4],hrs_blocks_square_s_low[5],hrs_blocks_square_s_low[6],hrs_blocks_square_s_low[7]);
//delay(1);
Hifi_HIFI_Config_HRS_V_blocks($BBID,hrs_blocks_square_s_low[0],hrs_blocks_square_s_low[1],hrs_blocks_square_s_low[2],hrs_blocks_square_s_low[3],hrs_blocks_square_s_low[4],hrs_blocks_square_s_low[5],hrs_blocks_square_s_low[6],hrs_blocks_square_s_low[7]);
delay(1);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//Square_S_nominal
Hifi_HIFI_Config_HRS_H_blocks($BBID,hrs_blocks_square_s_nom[0],hrs_blocks_square_s_nom[1],hrs_blocks_square_s_nom[2],hrs_blocks_square_s_nom[3],hrs_blocks_square_s_nom[4],hrs_blocks_square_s_nom[5],hrs_blocks_square_s_nom[6],hrs_blocks_square_s_nom[7]);
//delay(1);
Hifi_HIFI_Config_HRS_V_blocks($BBID,hrs_blocks_square_s_nom[0],hrs_blocks_square_s_nom[1],hrs_blocks_square_s_nom[2],hrs_blocks_square_s_nom[3],hrs_blocks_square_s_nom[4],hrs_blocks_square_s_nom[5],hrs_blocks_square_s_nom[6],hrs_blocks_square_s_nom[7]);
delay(1);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//Square_S_high
Hifi_HIFI_Config_HRS_H_blocks($BBID,hrs_blocks_square_s_high[0],hrs_blocks_square_s_high[1],hrs_blocks_square_s_high[2],hrs_blocks_square_s_high[3],hrs_blocks_square_s_high[4],hrs_blocks_square_s_high[5],hrs_blocks_square_s_high[6],hrs_blocks_square_s_high[7]);
//delay(1);
Hifi_HIFI_Config_HRS_V_blocks($BBID,hrs_blocks_square_s_high[0],hrs_blocks_square_s_high[1],hrs_blocks_square_s_high[2],hrs_blocks_square_s_high[3],hrs_blocks_square_s_high[4],hrs_blocks_square_s_high[5],hrs_blocks_square_s_high[6],hrs_blocks_square_s_high[7]);
delay(1);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
//}
}
/////////////////////////////////////////////////////////////////
// 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};
}
////////////////////////////////////////////////////////////////////////////
// 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();
}
}
}
// LCU configuration into NOMINAL mode, procedure
// Uses best guess D2 voltage from confgilcu table
// It then uses the new TM page dump TC from the MIB
procedure LCU_config_nominal_w_TMPageDump_proc_fm {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //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","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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, and clip to blue max
double drain2_bluemax = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq);
result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq);
drain2_v = min(result[0]{0},drain2_bluemax);
//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_w_TMPageDump_block_fm(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);
//
}
// WBS overall attenuator FM functional test, block
block FT_WBS_att_overall_COMB_fm HIFI 3714 {
string band = "1a"; // HIFI band
int integ_time = 4; //Total integration time in sec.
string laser_H = "Laser1" in ["Laser1","Laser2"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2"]; //WBS-V laser to be set ON
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//
//Set zero and comb on
Hifi_HIFI_Single_cmd($BBID,"HWH_ZERO_ON");
Hifi_HIFI_Single_cmd($BBID,"HWV_ZERO_ON");
Hifi_HIFI_Single_cmd($BBID,"HWH_COMB_ON");
Hifi_HIFI_Single_cmd($BBID,"HWV_COMB_ON");
delay(2);
//
//Initial configuration: overall attenuators set to max., individual attenuators to 3
//H-Polarization
//
{double,string}[] result = ConfigurationReader("name_configwbs",["hwh_heater","hwh_latchup_s"],band,0.0);
string hwh_laser1_s = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
int hwh_heater = iround(result[0]{0});
string hwh_latchup_s = result[1]{1};
int hwh_att_band4 = 3;
int hwh_att_band3 = 3;
int hwh_att_band2 = 3;
int hwh_att_band1 = 3;
int hwh_att_in = 16;
//
result = ConfigurationReader("name_delays",["wbs_config_delay"],band,0.0);
int wbs_config_delay = iround(result[0]{0});
//
//V-Polarization
//
result = ConfigurationReader("name_configwbs",["hwv_heater","hwv_latchup_s"],band,0.0);
string hwv_laser1_s = "OFF";
string hwv_laser2_s = "OFF";
if(laser_V == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_V == "Laser2") {
hwv_laser2_s = "ON";
}
int hwv_heater = iround(result[0]{0});
string hwv_latchup_s = result[1]{1};
int hwv_att_band4 = 3;
int hwv_att_band3 = 3;
int hwv_att_band2 = 3;
int hwv_att_band1 = 3;
int hwv_att_in = 16;
//
//Loop on overall attenuators
for(int i = 0 .. 15) {
// Change the value of the main attenuator
//========================================
hwh_att_in = hwh_att_in - 1;
hwv_att_in = hwv_att_in - 1;
// Set WBS
//========
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
//
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
//
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
}
//Set att. to max.
WBS_config_proc_max_att_w_laser_fm(band,laser_H,laser_V);
//
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Spectral Scan - Load Chop Ref",{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,imin(data_time,data_time_off));
{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);
// Final message to check for both polarizations
PolarizationMessage(hr1{0},hr2{0},wb1{0},wb2{0});
// 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}};
}
//HIFI-COP-2.1-FTUnp - goes into dissipative mode
obs HifiEng_FT_unpumped_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//General parameters in use
int integ_time = 4;
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"start");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(FT_unpumped_w_att_setting(band,hrs_mode,integ_time,backend));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
FT_unpumped_w_att_setting(band,hrs_mode,integ_time,backend);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
// 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 {
}{
//Page 7AH dump
Hifi_HIFI_LCU_read_settings();
//It will use one single MIB TC, and clear the error flag at end
Hifi_HIFI_LCU_all_tuning_hk();
//
delay(1);
}
////Obsolete block: use procedure instead.
// Move chopper
block Chopper_block_fm HIFI 3206 {
double chopper = 0.0;
}{
// Start_block() ;
// chopper = Check_Chopper_Prime_Redundant(chopper);
// Hifi_HIFI_CPR_Chopper_Rot ($BBID,chopper);
// Hifi_HIFI_non_periodic_hk_FCU (); //To get sent voltage
// delay (1) ;
error("Obsolete block. Use Chopper_Rotation_proc_fm instead");
}
//General script to clear error flags and set to nominal, block
block LCU_enable_some_bands_block_fm HIFI 3770 {
int hl_maskband = 16383; // bit description of bands to be enabled
}{
//
//switch to standby
{double,string}[] result = ConfigurationReader("name_delays",["stdby_delay"],"0",0.0);
int stdby_delay = iround(result[0]{0});
Hifi_HIFI_HL_Standby($BBID);
delay(stdby_delay);
//Enable all bands
Hifi_HIFI_Conf_LCU_internal($BBID,hl_maskband,"RESET","RESET",256);
//LSU_delta_f: 256 = 88mV
//
}
// Switch HIFI from intermediate to standby I, mode
// Assumed to have switched on and booted ICU when starting this mode
// Will end in standby I mode, i.e. chopper, upconverter, and HBB OFF.
mode HifiManCmd_HIFI_global_switch_on_ops {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
string chopper_loop = "OPEN" in ["OPEN","CLOSE"]; //chopper loop status
}{
Mode_status_check_intermediate();
mois_comment("HIFI global switch ON: successively switch ON subsystems");
mois_tmcheck("The HIFI ICU must have been switched on and successfully booted before to execute this procedure.");
StartMode_block_ops();
//Switch on units
HIFI_global_switch_on_proc_ops(prime_or_redundant);
//from moc_1.2: use proc instead of block
//FPU start-up
mois_step("Set HIFI FPU to band 0 with chopper loop " + chopper_loop);
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
if(chopper_loop == "OPEN") {
result = ConfigurationReader("name_chopper",["chop_startup_warm"],"0",0.0);
}
Init_MSA_ops("0",chopper_loop,0.0,result[0]{0},"ON",prime_or_redundant);
StopMode_block_mois();
Mode_status_check_standby_I(chopper_loop,"up",prime_or_redundant);
}
// 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);
}
}
////////////////////////////////////////////
//Block and procedure to test new SEU
//recognition scheme
//DT - 12-03-2010
////////////////////////////////////////////
//Block to modify a certain LCU S/W address
block LCU_simulate_upset_block_fm HIFI 3992 {
int location = 0x7ffe in [0,0x7ffe];
int value = 0x0 in [0,0xffff];
}{
{int}[] content = [{value}];
int check = checksum("short",[value]);
Hifi_HIFI_load_LCU(location,1,content,check);
}
////////////////////////////////////
// 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 Engineering - DBS Raster Map halfThrow slowChop",{data_time,0,0,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval});
ChopMessages(false,data_time,n_switch_on);
RasterSizeMessages(lineDistance,stepsize,nlines,npoints,false);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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 chopped hotcold, block
block Hot_cold_fastchop_fm HIFI 3225 {
string band = "1a";
int integ_time = 8; //Total integration time for delay computation
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,etc
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast
int n_wbs1 = 20;
int n_hrs_trans = 1;
}{
//Start_block();
//Rotate chopper: assume we come from M3: no rotation as this is done in the fastchop_spectro
//Chopper_Rotation_proc_fm(band,"chop_M3_ang","chop_hot_ang");
//Fetch respective chopper angles
{double,string}[] result = ConfigurationReader("name_confilfpu",["chop_hot","chop_cold"],band,0.0);
double chop_hot = result[0]{0};
double chop_cold = result[1]{0};
//
//Compute data-rate
double[] rates = ILT_datarate_proc_fm(band,backend,"fastchop",integ_time);
//Take spectrum
// set data rates
non_ess_hk_data_rate(rates[2] / 1024.0);
data_rate(rates[0] / 1024.0);
//
HIFI_Spectr_fast_chop_proc_fm(chop_hot,chop_cold,n_wbs1,n_hrs_trans);
Apply_Fast_Chop_delay(integ_time,1,band,backend);
// reset data rates
non_ess_hk_data_rate(rates[1] / 1024.0);
data_rate(0.0);
}
// Preliminary LO scan with HRS 0-lag measured, procedure
procedure Proc_LO_scan_w_HRS_lag {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double[] lo_freq_input = [500.0,500.15,0.02]; //Start, end and step lo_freq for the LO scan
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total (co-added) integration time of a phase in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Tune at the first frequency
LO_tuning_block_fm(band,lo_freq_input[0]);
//
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_cold_ang");
//Look at CBB
//
//WBS calibration and backend tuning
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
WBS_tune_proc_fm(band);
}
if(backend == "hrs" || backend == "both" || backend == "hrsFast") {
HRS_tune_block_fm(band);
}
//
//Configure spectrometers integration
int[] res = Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
//Loop on LO frequencies. It is assumed that the LO is tuned at the initial frequency
double lo_freq = lo_freq_input[0];
while(lo_freq <= lo_freq_input[1]) {
//Set synthesizer to new LO freq.
LCU_config_nominal_noretune_block_fm(band,lo_freq,lo_freq_input[0]);
//
//For bands with diplexer, update diplexer setting
double band_nb = GetBandCode(band);
if(band_nb <= 2.0 || band_nb == 5.0) {
double diplex_H = 0.0;
//For bands 1, 2 and 5
double diplex_V = 0.0;
} else {
double[] result_dip = Get_Diplexer_setting(band,lo_freq);
diplex_H = result_dip[0];
diplex_V = result_dip[1];
Set_Diplexer_current_block_fm(diplex_H,diplex_V);
}
//Take total power spectroscopy
Spectro_total_power_block_fm(band,res,backend);
//Increase lo_freq
lo_freq = lo_freq + lo_freq_input[2];
}
}
/////////////////////////////////////////////////////////////////
// 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 - OTF Map Frequency Switch noRef",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
// Vector scan calibration for a given LO band
// Merged with M1 control
procedure Vecscan_calibration_M1_proc_fm_COP {
string band = "5b" in ["5b","5b"]; // HIFI band
}{
//
LCU_switchon_proc_fm(band);
//Wait an extra delay of 1 min for short term stabilization
delay(60);
//
//Get the list of frequencies to be used for the scan
//At the moment the test is ad hoc for 5b between 1258 and 1259.999 GHz
//string tab = "config_vecscan.config";
//double bandnb = GetBandCode(band);
double lofreqlow = 1258.0;
//dlookup(tab,"" + iceil(bandnb),"lofreqlow");
double lofreqhigh = 1259.999;
//dlookup(tab,"" + iceil(bandnb),"lofreqhigh");
double lofreqstep = 1.0;
//dlookup(tab,"" + iceil(bandnb),"lofreqstep");
//
double current_LO = lofreqlow;
bool endreached = false;
//Array of M1/M2 to be used
if(band == "5b") {
double m1v_new = -4.2;
//Corresponds to second regime
double m2v_new = -3.7;
//Corresponds to second regime
double vd2_min = 1.7;
}
//Loop on key frequencies per LO band
while(current_LO <= lofreqhigh && endreached == false) {
//Configure FPU at that frequency
//SPR-2463: look at HBB
Init_MSA_HBB_fm(band,"CLOSE",current_LO,"ON");
//
//Perform vector scan within BLUE limits at that frequency
Vector_scan_w_M1M2D2_block_fm(band,current_LO,m1v_new,m2v_new,vd2_min);
//
//sanity check
//double[] result_dip = Get_Diplexer_setting(band,current_LO);
message("LO freq " + current_LO);
//Check last LO freq done
if(current_LO == lofreqhigh && endreached == false) {
endreached = true;
}
//Increase LO freq: truncate if step too high
current_LO = current_LO + lofreqstep;
if(current_LO > lofreqhigh && endreached == false) {
current_LO = lofreqhigh;
}
}
//
}
////////////////////////////////////
// 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;
}
//////////////////////////////////////////////////////////
// Stand-by configuration
////////////////////////////
//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_fm HIFI 3629 {
}{
error("This block is deprecated. Transitions to standby1 are only supported by LCU_standby1_block_mois");
//
///Start_block();
///{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);
}
//PDU switch off of a S/S, procedure
procedure PDU_switch_off_proc_ops {
string subsystem = "ICU_Prime" in ["ICU_Prime","ICU_Red","LO_Prime","LO_Red","WBS_H","WBS_V","HRS_H","HRS_V"];
}{
////HifiIltEgse_PDU_switch_off($BBID,subsystem); //The TEI command: WILL BE DONE BY SPACON
mois_spacon("Please power OFF Sub-System " + subsystem);
//delay(1);
}
//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};
}
// Laser stabilization time for WBS, procedure
procedure FT_WBS_stabilization_time_proc_fm {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
int n = 100; //Number of load pairs to be measured
string laser_H = "Laser1" in ["Laser1","Laser2"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2"]; //WBS-V laser to be set ON
int integ_time = 4; //Total integration time in sec. to be set at end of test
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//
//Configure WBS
WBS_config_w_laser_block_fm(band,laser_H,laser_V);
//Attenuator Tune
WBS_tune_proc_fm(band);
//Integration
Stability_backend_fm(band,n,integ_time,backend,["wb1","wb1"]);
//Configure spectrometers integration back to default
Configure_Spectrometer_proc_fm(band,integ_time,["wb1","wb1"],backend);
//Do zero and COMB
WBS_calib_fm(band);
//Set att. to max.
WBS_config_max_att_w_laser_block_fm(band,laser_H,laser_V);
//
}
//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:
//Internal LO relative to IF centre
double if_centre = 6.0;
//
//Resolution mode
string hrs_mode_h = "hr";
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];
if(hrs1{0}) {
// Resolution strings and LO assignment
if(hrs1{1} == 1) {
// medium resolution
hrs_mode_h = "mr";
hrsH_LO = [if_centre + hrs1{2}[0] / 1000.0,if_centre + hrs1{2}[2] / 1000.0,if_centre + hrs1{2}[3] / 1000.0,if_centre + hrs1{2}[1] / 1000.0];
}
if(hrs1{1} == 2) {
// low resolution
hrs_mode_h = "lr";
hrsH_LO = [if_centre + hrs1{2}[0] / 1000.0,if_centre + hrs1{2}[3] / 1000.0,if_centre + hrs1{2}[1] / 1000.0,if_centre + hrs1{2}[2] / 1000.0];
}
if(hrs1{1} == 3) {
// wide-band resolution
hrs_mode_h = "wb";
}
}
string hrs_mode_v = "hr";
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];
if(hrs2{0}) {
// Resolution strings and LO assignment
if(hrs2{1} == 1) {
// medium resolution
hrs_mode_v = "mr";
hrsV_LO = [if_centre + hrs2{2}[0] / 1000.0,if_centre + hrs2{2}[2] / 1000.0,if_centre + hrs2{2}[3] / 1000.0,if_centre + hrs2{2}[1] / 1000.0];
}
if(hrs2{1} == 2) {
// low resolution
hrs_mode_v = "lr";
hrsV_LO = [if_centre + hrs2{2}[0] / 1000.0,if_centre + hrs2{2}[3] / 1000.0,if_centre + hrs2{2}[1] / 1000.0,if_centre + hrs2{2}[2] / 1000.0];
}
if(hrs2{1} == 3) {
// wide-band resolution
hrs_mode_v = "wb";
}
}
//
// Apply
string[] hrs_mode = [hrs_mode_h,hrs_mode_v];
HRS_config_resol_block_aot(band,hrs_mode);
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);
//
}
/////////////////////////////////////////////////////////////////
// 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;
}
//HIFI-COP-3-Dipscan
obs HifiEng_Dipscan_calibration_COP {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Diplexer_survey_proc_COP(band));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Diplexer_survey_proc_COP(band);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
// Single IV curve procedure: always called from a block !
procedure IVcurve {
string band = "1a";
double bias_min = -6.0;
double bias_max = 6.0;
int step_count = 131;
double magnet_current_h = 15.0; // magnet current, set first (mA)
double magnet_current_v = 15.0; // magnet current, set first (mA)
double bias_h = 2.2; // bias voltage, set before exit (mV)
double bias_v = 2.2; // bias voltage, set before exit (mV)
}{
//In case of band 6 or 7, set first to 4mV
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_max_h","bias_max_v"],band,0.0);
//First go to 4mV
Mixerbias(result[0]{0},result[1]{0});
}
//
int duration_ivcurve = 0;
double step_duration = 0.1;
int max_per_command = 40;
int steps = 0;
int steps_done = 0;
double step = Stepsize(bias_min,bias_max,step_count,"hifi_HIF_mxbias_step_V");
double margin = Stepmargin(bias_min,bias_max,"hifi_HIF_mxbias_step_V");
int steps_wanted = 1 + iceil((bias_max - bias_min) / step);
// force the last portion to less than max_per_command:
if(max_per_command * (steps_wanted / max_per_command) == steps_wanted) {
steps_wanted = steps_wanted - 1;
}
double bias_start = bias_min;
while(steps_done < steps_wanted) {
steps = steps_wanted - steps_done;
if(steps > max_per_command) {
steps = max_per_command;
}
bias_start = bias_min + double(steps_done) * step;
Hifi_HIFI_FCU_parameter_scan($BBID,steps,1,step_duration,bias_start,bias_start,step + margin,magnet_current_h,magnet_current_v,0.0);
duration_ivcurve = iceil(double(steps) * step_duration);
delay(duration_ivcurve + 2);
steps_done = steps_done + steps;
}
//Set back to value on exit
//In case of band 6 or 7, set first to 4mV
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
result = ConfigurationReader("name_confilfpu",["bias_max_h","bias_max_v"],band,0.0);
//First go to 4mV
Mixerbias(result[0]{0},result[1]{0});
}
//
Mixerbias(bias_h,bias_v);
}
//Check D2 is within the BLUE ranges
bool procedure Check_D2_vs_BLUE_proc_fm {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
double drain2_v = 1.6; //D2_V to compare to blue table
}{
bool go_ahead = true;
//Fetch index
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));
//
if(band == "1a" && (drain2_v < result[0]{0} || drain2_v > result[1]{0})) {
go_ahead = false;
}
if(band == "1b" && (drain2_v < result[2]{0} || drain2_v > result[3]{0})) {
go_ahead = false;
}
if(band == "2a" && (drain2_v < result[4]{0} || drain2_v > result[5]{0})) {
go_ahead = false;
}
if(band == "2b" && (drain2_v < result[6]{0} || drain2_v > result[7]{0})) {
go_ahead = false;
}
if(band == "3a" && (drain2_v < result[8]{0} || drain2_v > result[9]{0})) {
go_ahead = false;
}
if(band == "3b" && (drain2_v < result[10]{0} || drain2_v > result[11]{0})) {
go_ahead = false;
}
if(band == "4a" && (drain2_v < result[12]{0} || drain2_v > result[13]{0})) {
go_ahead = false;
}
if(band == "4b" && (drain2_v < result[14]{0} || drain2_v > result[15]{0})) {
go_ahead = false;
}
if(band == "5a" && (drain2_v < result[16]{0} || drain2_v > result[17]{0})) {
go_ahead = false;
}
if(band == "5b" && (drain2_v < result[18]{0} || drain2_v > result[19]{0})) {
go_ahead = false;
}
if(band == "6a" && (drain2_v < result[20]{0} || drain2_v > result[21]{0})) {
go_ahead = false;
}
if(band == "6b" && (drain2_v < result[22]{0} || drain2_v > result[23]{0})) {
go_ahead = false;
}
if(band == "7a" && (drain2_v < result[24]{0} || drain2_v > result[25]{0})) {
go_ahead = false;
}
if(band == "7b" && (drain2_v < result[26]{0} || drain2_v > result[27]{0})) {
go_ahead = false;
}
if(go_ahead == false) {
//debug_print("go_ahead is: " + go_ahead);
error("D2 voltage not within allowed range for band " + band);
}
return go_ahead;
}
//Reduced version: IVC
//HIFI-COP-7.2-LO_FT
procedure LO_FT_IVC_COP_proc_ops {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//Switch-off LCU
LCU_switch_off_block_fm();
delay(1);
//General parameters in use
string multiplier = "ALL";
int operation_delay = 0;
//
double[] cresult_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = cresult_d[0];
//applies to cold LO
//
Measure_LCU_IV_proc_fm(band,multiplier,operation_delay);
//
}
////////////////////////////////////
// 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 Single Point - Load Chop noRef",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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 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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Map Position Switch",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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
// !!! The routine is 1s too short to get rid of all the data.
// It must be externally guaranteed that there is always a dangling
// second without data frames produced !!!
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
}{
Tune_HRS_aot(band);
}
////////////////////////////////////////////////////////////////////////////
// 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();
}
}
}
/////////////////////////////////////////////////////////////////
// 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 Spectral Scan - Load Chop Ref",{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,imin(data_time,data_time_off));
{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);
// Final message to check for both polarizations
PolarizationMessage(hr1{0},hr2{0},wb1{0},wb2{0});
// 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}};
}
//Unlock LCU communication lock - SCR-3071
mode HifiManCmd_LCU_lock_clear {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to unlock LCU communication from the OBSW");
//StartMode_block_ops();
//
mois_spacon("Check that the HK HI_LCU_commands is set to DISABLED");
mois_step("Unlock LCU communication");
LCU_lock_clear_block_mois();
//
StopMode_block_mois();
}
////////////////////////////////////////////////////////////////////////
// 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;
}
//OBS autonomous function against unpatched LCU - SCR-3070
mode HifiManCmd_Standby0_FDIR_disable {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to disable check of LCU entering standby0");
//StartMode_block_ops();
//
mois_spacon("Verify that HM125190 (HI_au_LCUmode_S) is ON");
mois_step("Disable Standby0 watchdog function");
Disable_Standby0_FDIR_block_mois();
//
mois_spacon("Verify that HM125190 (HI_au_LCUmode_S) is OFF");
StopMode_block_mois();
}
//////////////////////////////////////////////////////////////////////
// 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};
}
//Set LCU6La back to standby status, procedure
procedure LCU6La_standby_proc_fm {
string band = "6a"; // HIFI band
double lo_freq = 1500.0 in [1410.0,1575.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
// WBS zero, block
block WBS0_fm HIFI 3604 {
string band = "1a"; // HIFI band
}{
//Start_block();
//Two options are possible: CUS sequence or automatic OBS command
//Option1: CUS sequence (has its own delay)
//WBS0_fm_proc(band);
//Option2: OBS command
Hifi_HIFI_WBS_Zero($BBID);
//Get delay
{double,string}[] result_d = ConfigurationReader("name_delays",["wbs_zero_delay"],band,0.0);
int wbs_zero_delay = iround(result_d[0]{0});
delay(wbs_zero_delay);
}
//Get best guess D2 from look-up table
double procedure Get_BEST_GUESS_D2_proc_fm {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO Frequency
}{
//Fetch best guess for D2
string name_configlcutune = "name_configlcu_a";
if(band == "1b" || band == "2b" || band == "3b" || band == "4b" || band == "5b" || band == "6b" || band == "7b") {
name_configlcutune = "name_configlcu_b";
}
//
{double,string}[] result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq);
//
return result[0]{0};
}
// Switch HIFI off, procedure
// Prime and Redundancy are both called, regardless of which is effectively used
//
procedure HIFI_global_switch_off_fm {
}{
//Sequentially notify PDU off then switch off S/S
//This maybe non-instictive order is due to an ICU bug that
//screws things up when the ICU tries to get HK from a switched off S/S
//
//LOU
Hifi_HIFI_notify_PDU_status("ON","OFF","ON","ON","ON","ON");
//HifiIltEgse_PDU_switch_off($BBID,"LO_Prime");
//HifiIltEgse_PDU_switch_off($BBID,"LO_Red");
//WBS-H
Hifi_HIFI_notify_PDU_status("ON","OFF","ON","OFF","ON","ON");
//HifiIltEgse_PDU_switch_off($BBID,"WBS_H");
//WBS-V
Hifi_HIFI_notify_PDU_status("ON","OFF","OFF","OFF","ON","ON");
//HifiIltEgse_PDU_switch_off($BBID,"WBS_V");
//HRS-H
Hifi_HIFI_notify_PDU_status("ON","OFF","OFF","OFF","ON","OFF");
//HifiIltEgse_PDU_switch_off($BBID,"HRS_H");
//HRS-V
Hifi_HIFI_notify_PDU_status("ON","OFF","ON","OFF","OFF","OFF");
//HifiIltEgse_PDU_switch_off($BBID,"HRS_V");
//ICU
Hifi_HIFI_notify_PDU_status("OFF","OFF","OFF","OFF","OFF","OFF");
//HifiIltEgse_PDU_switch_off($BBID,"ICU_Prime");
//HifiIltEgse_PDU_switch_off($BBID,"ICU_Red");
//At that stage, the instrument is idle...
}
// Magnet current scan, fast, procedure.
// Mixer current as a function of magnet current.
procedure Magnet_scan_fast_proc {
string band = "1a"; // HIFI band //Setting file
double magnet_current_min_h = -10.0; //minimum magnet current H
double magnet_current_max_h = 15.0; //maximum magnet current H
double magnet_current_min_v = -10.0; //minimum magnet current V
double magnet_current_max_v = 15.0; //maximum magnet current V
int n_steps = 100; //number of steps
double lo_freq = 522.0; //LO frequency
}{
//
Magnet_scan_fast_fm(band,magnet_current_min_h,magnet_current_max_h,magnet_current_min_v,magnet_current_max_v,n_steps,lo_freq);
//Back to nominal values
if(band != "0") {
{double,string}[] result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,0.0);
}
if(band == "0") {
result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v","magnet_standby_h","magnet_standby_v","bias_standby_h","bias_standby_v"],band,0.0);
}
//First set magnet to maximum to avoid hysteresis
double magnetcurrent_max_h = result[0]{0};
double magnetcurrent_max_v = result[1]{0};
Set_Magnet_current_block_fm(magnetcurrent_max_h,magnetcurrent_max_v);
//Nominal values
result = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v","norm_bias_h","norm_bias_v"],band,lo_freq);
Set_Magnet_current_block_fm(result[0]{0},result[1]{0});
//Also set bias voltages back to nominal values
Mixerbias_block_fm(result[2]{0},result[3]{0});
}
//Checksum verification in MTL
obs HifiEng_recalc_LCU_checksum_MTL {
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(LcuChecksumRecalc_ops("R"));
// 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) {
// Test execution
LcuChecksumRecalc_ops("R");
}
if(state[0] == 5) {
//HIFISetHK("normal",true); // -> superfluous
HIFICloseObs();
}
}
}
// Standing wave analysis, mode
// For COP, we observe mostly sky-CBB, and sometimes sky-HBB and sky-sky pairs
//HIFI-COP-3-StWv1
obs HifiEng_standing_wave_noretune_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
int freq_index = 1; //The frequency index to consider: 1 to 4
string los_code = "sc" in ["sc","sh","ss"]; //The line-of-sight code: sc (sky-CBB), sh (sky-HBB), ss (sky-sky)
}{
//General parameters in use
string backend = "both";
string[] hrs_mode = ["mr","mr"];
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Standing_wave_noretune_COP_proc_ops(band,backend,hrs_mode,freq_index,los_code));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Standing_wave_noretune_COP_proc_ops(band,backend,hrs_mode,freq_index,los_code);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
// 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);
}
// WBS overall attenuator FM functional test, block
// Done for laser1
block FT_WBS_att_individual_fm HIFI 3707 {
string band = "1a"; // HIFI band
int integ_time = 4; //Total integration time in sec.
string laser_H = "Laser1" in ["Laser1","Laser2"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2"]; //WBS-V laser to be set ON
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//
//Set zero and comb off
Hifi_HIFI_Single_cmd($BBID,"HWH_ZERO_OFF");
Hifi_HIFI_Single_cmd($BBID,"HWV_ZERO_OFF");
Hifi_HIFI_Single_cmd($BBID,"HWH_COMB_OFF");
Hifi_HIFI_Single_cmd($BBID,"HWV_COMB_OFF");
delay(2);
//
//Initial configuration: overall attenuators set to 0, individual attenuators to max.
//H-Polarization
//
{double,string}[] result = ConfigurationReader("name_configwbs",["hwh_heater","hwh_latchup_s"],band,0.0);
string hwh_laser1_s = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
int hwh_heater = iround(result[0]{0});
string hwh_latchup_s = result[1]{1};
int hwh_att_band4 = 8;
int hwh_att_band3 = 8;
int hwh_att_band2 = 8;
int hwh_att_band1 = 8;
int hwh_att_in = 0;
//
result = ConfigurationReader("name_delays",["wbs_config_delay"],band,0.0);
int wbs_config_delay = iround(result[0]{0});
//
//V-Polarization
//
result = ConfigurationReader("name_configwbs",["hwv_heater","hwv_latchup_s"],band,0.0);
string hwv_laser1_s = "OFF";
string hwv_laser2_s = "OFF";
if(laser_V == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_V == "Laser2") {
hwv_laser2_s = "ON";
}
int hwv_heater = iround(result[0]{0});
string hwv_latchup_s = result[1]{1};
int hwv_att_band4 = 8;
int hwv_att_band3 = 8;
int hwv_att_band2 = 8;
int hwv_att_band1 = 8;
int hwv_att_in = 0;
//
//Loop on overall attenuators
for(int i = 0 .. 7) {
// Change the value of the individual attenuators
//===============================================
hwh_att_band4 = hwh_att_band4 - 1;
hwh_att_band3 = hwh_att_band3 - 1;
hwh_att_band2 = hwh_att_band2 - 1;
hwh_att_band1 = hwh_att_band1 - 1;
hwv_att_band4 = hwv_att_band4 - 1;
hwv_att_band3 = hwv_att_band3 - 1;
hwv_att_band2 = hwv_att_band2 - 1;
hwv_att_band1 = hwv_att_band1 - 1;
// Set WBS
//========
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
//
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
//
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
}
//Set att. to max.
WBS_config_proc_max_att_w_laser_fm(band,laser_H,laser_V);
//
}
//HIFI LO tuning with choice of mixer to be used, block
//Target current is read from look-up table
block LO_tuning_w_mixerchoice_block_fm HIFI 3675 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
string mixer_polarization = "H" in ["H","V","B"]; //The polarization to be used for the tuning
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Start_block();
//
//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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = result[1]{1};
//
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};
//
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,lo_freq);
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 middle_d2 = result[0]{0};
double drain2_v_start = min(middle_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);
//
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
//Send command
HIFI_Configure_LCU_proc_fm(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);
//
//delay(5); //to settle at this value
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "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_nom_3b($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 == "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);
}
//
delay(1);
//
//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
HIFI_HL_store_tm_only_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//
// Magnet current scan, fast, block.
// Mixer current as a function of magnet current.
block Magnet_scan_fast_fm HIFI 3270 {
string band = "1a"; // HIFI band
double magnet_current_min_h = -15.0; //minimum magnet current H
double magnet_current_max_h = 10.0; //maximum magnet current H
double magnet_current_min_v = -15.0; //minimum magnet current V
double magnet_current_max_v = 10.0; //maximum magnet current V
int n_steps = 100; //number of steps
double lo_freq = 522.0; //LO frequency
}{
Start_block();
{double,string}[] result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,0.0);
double magnetcurrent_max_h = result[0]{0};
double magnetcurrent_max_v = result[1]{0};
//We use special biasing to evidence the minima in the magnet scan
result = ConfigurationReader("name_confilmix",["bias4magn_h","bias4magn_v"],band,lo_freq);
double bias_h = result[0]{0};
double bias_v = result[1]{0};
Mixerbias(bias_h,bias_v);
//
int steps = 0;
int steps_done = 0;
double step_duration = 0.1;
int steps_wanted = n_steps;
if(steps_wanted < 1) {
steps_wanted = 1;
}
double magnet_current_h = 0.0;
double stepsize_h = 0.0;
double magnet_current_v = 0.0;
double stepsize_v = 0.0;
if(steps_wanted > 1) {
stepsize_h = (magnet_current_max_h - magnet_current_min_h) / (double(steps_wanted) - 1.0);
stepsize_v = (magnet_current_max_v - magnet_current_min_v) / (double(steps_wanted) - 1.0);
}
//
//Set magnet to maximum to avoid hysteresis
Hifi_HIFI_CH1_MX_MG_C($BBID,magnetcurrent_max_h);
Hifi_HIFI_CV1_MX_MG_C($BBID,magnetcurrent_max_v);
delay(1);
//
//Start scan: from max. to min. magnet downward.
while(steps_done < steps_wanted) {
steps = steps_wanted - steps_done;
if(steps > n_steps) {
steps = n_steps;
}
magnet_current_h = magnet_current_max_h - double(steps_done) * stepsize_h;
magnet_current_v = magnet_current_max_v - double(steps_done) * stepsize_v;
Hifi_HIFI_FCU_parameter_scan($BBID,1,1,step_duration,bias_h,bias_v,0.0,magnet_current_h,magnet_current_v,0.0);
//Sets magnet current
delay(2);
steps_done = steps_done + 1;
}
}
// LCU1a configuration and tuning, procedure
procedure LCU1a_config_tune_proc_fm {
string band = "1a"; // HIFI band
double lo_freq = 500.0 in [488.0,552.0]; //LO frequency
double drain_2_factor = 100.0; //Percentage factor of the targetted drain voltage
}{
error("This module is obsolete: use LO_tuning_block_fm instead");
}
// 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);
}
//Readback of LCU safety table, block
block LcuSafetyTableReadback_ops HIFI 7901 {
}{
StartBlock_ops();
//
for(int band = 1 .. 7) {
for(int fIndex = 0 .. 31) {
Hifi_HIFI_non_periodic_hk_LCU(fIndex,"channel_" + band + "a");
delay(2);
Hifi_HIFI_non_periodic_hk_LCU(fIndex,"channel_" + band + "b");
delay(2);
}
}
}
// Special configuration and data taking for FSW response time
block FSW_Response_time_block_fm HIFI 3688 {
string hrs_polar = "H" in ["H","V","B"]; //HRS polarizations in use
int[] del_wbs_param = [10,200,10,100]; //starting, ending and step value for del_wbs
}{
//
//Additional "constant" parameters
{double,string}[] result = ConfigurationReader("name_delays",["add_hrs","add_wbs","add_jitter","wbs_init","wbs_chunksize","tacc_add","hrs_phase"],"0",0.0);
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
//
// Get fixed parameters from configuration and calibration files
// Command jitter time is the default delay
result = ConfigurationReader("name_delays",["add_jitter"],"0",0.0);
int add_jitter = iround(result[0]{0});
//Fetch default parameters
result = ConfigurationReader("name_confilspec",["del_hrs","del_wbs","t_acc_wbs","t_acc_hrs","n_wbs_integr","n_hrs_integr","r_hrs","wbsh_offset1","wbsh_width1","wbsh_offset2","wbsh_width2","wbsh_offset3","wbsh_width3","wbsh_offset4","wbsh_width4","wbsv_offset1","wbsv_width1","wbsv_offset2","wbsv_width2","wbsv_offset3","wbsv_width3","wbsv_offset4","wbsv_width4","hrs_rshift","wbs_rshift","hrsh_sel","hrsv_sel","wbs_packing"],"0",0.0);
//
// WBS delta time
int del_wbs = del_wbs_param[0];
// HRS delta time - should be zero
int del_hrs = add_jitter;
//Fixed integration time for this test
int n_data = 4;
int data_time = 1;
//Integration time for one phase if only one HRS polar
if(hrs_polar == "B") {
data_time = 2;
}
// Split total integration time
int tint = data_time * n_data * 1000;
// Accumulation time
// Ignores that total power can be slightly more efficient
int t_acc_wbs = (tint - wbs_init) / n_data - add_wbs - add_jitter - del_wbs;
// discretize in 10ms chunks
int nchunk = (t_acc_wbs - tacc_add) / wbs_chunksize;
t_acc_wbs = nchunk * wbs_chunksize + tacc_add;
// 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 = iceil(min(double(del_wbs_param[0]),double((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;
//No WBS
int wbsh_offset1 = 0;
int wbsh_width1 = 0;
int wbsh_offset2 = 0;
int wbsh_width2 = 0;
int wbsh_offset3 = 0;
int wbsh_width3 = 0;
int wbsh_offset4 = 0;
int wbsh_width4 = 0;
int wbsv_offset1 = 0;
int wbsv_width1 = 0;
int wbsv_offset2 = 0;
int wbsv_width2 = 0;
int wbsv_offset3 = 0;
int wbsv_width3 = 0;
int wbsv_offset4 = 0;
int wbsv_width4 = 0;
int hrs_rshift = 0;
int wbs_rshift = iround(result[24]{0});
int hrsh_sel = 0;
int hrsv_sel = 0;
if(hrs_polar == "H" || hrs_polar == "B") {
hrsh_sel = 255;
}
if(hrs_polar == "V" || hrs_polar == "B") {
hrsv_sel = 255;
}
string wbs_packing = result[27]{1};
//
//Now loop on del_wbs and trigger FSW spectro
int step = del_wbs_param[2];
while(del_wbs <= del_wbs_param[1]) {
//
//Configure integration to be done
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_offset1,wbsh_width1,wbsh_offset2,wbsh_width2,wbsh_offset3,wbsh_width3,wbsh_offset4,wbsh_width4,wbsv_offset1,wbsv_width1,wbsv_offset2,wbsv_width2,wbsv_offset3,wbsv_width3,wbsv_offset4,wbsv_width4,hrs_rshift,wbs_rshift,hrsh_sel,hrsv_sel,wbs_packing);
//
//Take spectrum
Hifi_HIFI_Spectr_freq_switch($BBID);
//Compute delay
result = ConfigurationReader("name_delays",["wbs_transfer_delay"],"0",0.0);
//
int wbs_packet_transfer_time = iround(result[0]{0});
int delay_fsw = n_wbs_start * data_time + wbs_packet_transfer_time / 1000;
//debug_print("Total power delay: " + delay_total_power + " sec");
//
//Apply delay
delay(delay_fsw);
//
//Increase step
del_wbs = del_wbs + step;
//Re-adjust spectrometer integration times
//WBS
t_acc_wbs = (tint - wbs_init) / n_data - add_wbs - add_jitter - del_wbs;
// discretize in 10ms chunks
nchunk = (t_acc_wbs - tacc_add) / wbs_chunksize;
t_acc_wbs = nchunk * wbs_chunksize + tacc_add;
//HRS
r_hrs = (t_acc_wbs + hrs_fullphase - add_jitter) / hrs_fullphase;
t_acc_hrs = iceil(min(double(del_wbs_param[0]),double((t_acc_wbs - add_jitter) / r_hrs - del_hrs - add_hrs)));
}
}
//HIFI-COP-2.1-DipCal2
obs HifiEng_Diplexer_calibration_hotcold_COP {
string band = "3" in ["3","4","6","7"]; // HIFI mixer band
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band + "a","both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Diplexer_calibration_hotcold_COP_proc_ops(band));
// 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();
HIFILCUChecksumAndSetHK(band + "a","fast",true);
}
if(state[0] == 3) {
// Test execution
Diplexer_calibration_hotcold_COP_proc_ops(band);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band + "b",false,"normal",true);
HIFICloseObs();
}
}
}
//HIFI LO tuning only for M1 investigation in 7b, block
//Target current is read from look-up table
block LO_tuning_w_M1_block_fm HIFI 3716 {
string band = "7b"; // HIFI band
double lo_freq = 1890.0; //LO frequency
double m1 = -5.0; //M1 multiplier voltage
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Start_block();
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//
//Get target mixer current
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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],band,lo_freq);
double plevel_v = result[0]{0};
double m1_v = m1;
//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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = result[1]{1};
//
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};
//
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,lo_freq);
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);
//The automatic tuning shall use the min of the nominal best-guess and Vd2max - 100mV
double middle_d2 = min(result[0]{0},drain2_bluemax - 0.1);
double drain2_v_start = min(middle_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) * middle_d2;
//drain2_v_start;
step_drain2_v = (drain2_v_end - drain2_v_start) / double(nsteps - 1);
//
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
//Send command
if(band == "3b") {
Hifi_HIFI_Conf_nom_LCU_ch3b($BBID,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);
//Send command: specific to M3 in 3b
delay(config_lo_delay);
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
} else {
//
//General command
HIFI_Configure_LCU_proc_fm(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);
}
//
//delay(5); //to settle at this value
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "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_nom_3b($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 == "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);
}
//
delay(1);
//
//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
HIFI_HL_store_tm_only_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//////////////////////////////////////////////////////////////////////
// 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};
}
// 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
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 telinit = telescopetimes[1];
// Initial slew time
int tend = telescopetimes[2];
// Final deceleration time
totaltime = totaltime + tend + telinit - initlength;
// 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();
HIFILCUChecksumAndSetHK(band,"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
}
//TM check when in standby II
procedure Mode_status_check_standby_II {
string laser_H = "Laser1" in ["Laser1","Laser2"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2"]; //WBS-V laser to be set ON
string chopper_loop = "OPEN" in ["OPEN","CLOSE"]; //chopper loop status
string sequence_order = "up" in ["down","up"]; //order in which sequence is done
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_comment("Checking instrument status in standby II mode");
//General checks: not applicable here: S/S should all be on here
//FCU checks
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["calibrator_current_on"],"0",0.0);
double calibcurrent = result_d[0]{0};
//Getting in band0 is only new when coming from primary
if(sequence_order == "down") {
mois_tmcheck("Check that parameter HF_DH1_MXBAND and HF_DV1_MXBAND are both 0");
}
//Checking if HBB is on important at any standby or primary stage
mois_tmcheck("Check that parameter HF_APR_CS_C is set to " + calibcurrent + " mA. If not, you can proceed but need to inform HIFI ICC.");
//Chopper voltage
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
result_d = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
if(chopper_loop == "OPEN") {
result_d = ConfigurationReader("name_chopper",["chop_startup_warm"],"0",0.0);
}
if(sequence_order == "down") {
mois_tmcheck("Check that parameter HF_DPR_CH_ROT is set to " + result_d[0]{0});
//Chopper loop status should always be monitored
mois_tmcheck("Check that parameter HF_DPR_CHLOOP_S is set to " + chopper_loop);
}
//
//WBS checks: although only lasers are changed, the whole configuration command is called
result_d = ConfigurationReader("name_configwbs",["hwh_latchup_s","hwv_latchup_s"],"0",0.0);
string hwh_latchup_s = "Low";
if(result_d[0]{1} == "Level2") {
hwh_latchup_s = "High";
}
string hwv_latchup_s = "Low";
if(result_d[1]{1} == "Level2") {
hwv_latchup_s = "High";
}
string hwh_laser1_s = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
string hwv_laser1_s = "OFF";
string hwv_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwv_laser2_s = "ON";
}
//
mois_tmcheck("Check that parameters HWH_Laser1_S, HWH_Laser2_S, HWV_Laser1_S and HWV_Laser2_S are respectively " + hwh_laser1_s + ", " + hwh_laser2_s + ", " + hwv_laser1_s + " and " + hwv_laser2_s);
mois_tmcheck("Check that both parameters HWH_Zero_S and HWV_Zero_S are ON");
mois_tmcheck("Check that both parameters HWH_Comb_S and HWV_Comb_S are OFF");
mois_tmcheck("Check that parameters HWH_LUP_level_S and HWV_LUP_level_S are " + hwh_latchup_s + " and " + hwv_latchup_s + " respectively");
mois_tmcheck("Check that parameter HWH_IN_ATT is set to 15, and parameters HWH_Band_1_ATT, HWH_Band_2_ATT, HWH_Band_3_ATT, HWH_Band_4_ATT are set to 7");
mois_tmcheck("Check that parameter HWV_IN_ATT is set to 15, and parameters HWV_Band_1_ATT, HWV_Band_2_ATT, HWV_Band_3_ATT, HWV_Band_4_ATT are set to 7");
//HRS Checks: HRS only modified if from primary to standbyII
if(sequence_order == "down") {
// Fetch HRS configuration parameters
//===================================
//H-polar
string hrs_filename_h = "name_confighrs_wb";
{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"],"0",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_wb";
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"],"0",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}];
//
mois_tmcheck("Check that parameters HRH_1U_ATT, HRH_1L_ATT, HRH_2U_ATT, HRH_2L_ATT, HRH_3U_ATT, HRH_3L_ATT, HRH_4U_ATT and HRH_4L_ATT are set to 15.5");
mois_tmcheck("Check that parameters HRV_1U_ATT, HRV_1L_ATT, HRV_2U_ATT, HRV_2L_ATT, HRV_3U_ATT, HRV_3L_ATT, HRV_4U_ATT and HRV_4L_ATT are set to 15.5");
mois_tmcheck("Check that parameters HRH_LOCK_LO1_S, HRH_LOCK_LO2_S, HRH_LOCK_LO3_S, HRH_LOCK_LO4_S, HRH_LOCK_LO5_S, HRH_LOCK_LO6_S, and HRH_LOCK_LO7_S are all Locked");
mois_tmcheck("Check that parameters HRV_LOCK_LO1_S, HRV_LOCK_LO2_S, HRV_LOCK_LO3_S, HRV_LOCK_LO4_S, HRV_LOCK_LO5_S, HRV_LOCK_LO6_S, and HRV_LOCK_LO7_S are all Locked");
Check_HRS_LO_proc_ops(["wb","wb"],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]);
}
//LOU Checks:
if(sequence_order == "down") {
mois_tmcheck("Check that parameter HL_MODE_S is standby1");
mois_tmcheck("Check that parameter HL_Channel_S is Off");
}
}
// Chopper calibration for a given mixer band, procedure
procedure Chopper_calibration_proc_fm {
int band = 1 in [1,7]; // HIFI mixer band
int integ_time = 4; //Integration time PER PHASE for the slowchop measurement
bool shutter_used = false;
bool sky = true; //whether or not we scan over M3 area
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3
}{
string chopmode = "slowchop";
//close shutter if necessary
if(shutter_used) {
//Shutter_rotate_proc_fm("closed");
}
//Tune backends on the hot load
Chopper_Rotation_block_fm("" + band + "a","chop_M3_ang","chop_hot_ang");
//Configure and tune backends
WBS_calib_fm("" + band + "a");
WBS_tune_proc_fm("" + band + "a");
HRS_tune_block_fm("" + band + "a");
//The chopper scan is done in slowchop mode to avoid short term instabilities
int[] res = Configure_Spectrometer_hc_slow_chop_proc_fm("" + band + "a",integ_time * 2,["wb1","wb1"],"both");
int total_time = res[0] * res[1];
int n_wbs1 = 0;
//we use the slowchop mode
int n_hrs_trans = 0;
//we use the slowchop mode
double chop_phase = 1.0;
//we use the slowchop mode
//
//If HEB bands, chop faster with fastchop: 1Hz
if(band > 5) {
chop_phase = 0.5;
res = Configure_Spectrometer_fast_chop_proc_fm("" + band + "a",integ_time * 2,chop_phase,["wb1","wb1"],"both");
total_time = iceil(chop_phase * double(res[1] * res[2]));
n_wbs1 = res[2];
n_hrs_trans = res[3];
chopmode = "fastchop";
}
//
//Get voltages for start and end positions, and number of steps
{double,string}[] result_d = ConfigurationReader("name_confilchopcalib",["chop_start","chop_end","chop_nstep","chop_start_sky","chop_end_sky","chop_nstep_sky"],"" + band + "a",double(band));
double chopper_pos_min = result_d[0]{0};
double chopper_pos_max = result_d[1]{0};
int n_steps = iround(result_d[2]{0});
if(sky) {
chopper_pos_min = result_d[3]{0};
chopper_pos_max = result_d[4]{0};
n_steps = iround(result_d[5]{0});
}
//
Chopper_scan_fm("" + band + "a",chopper_pos_min,chopper_pos_max,n_steps,total_time,"both",chopmode,n_wbs1,n_hrs_trans,false,shutter_used,hrs_mode,chop_phase);
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Spectral Scan - DBS fastChop",{data_time,0,n_switch_on,n_int_on,0,0,0,n_freq_point,n_cycles,load_interval});
ChopMessages(true,data_time,n_int_on);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hr1{0},hr2{0},wb1{0},wb2{0});
// 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,"dbs",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};
}
// Switch HIFI off, block
// Prime and Redundancy are both called, regardless of which is effectively used
//
block HIFI_global_switch_off_block_fm HIFI 3921 {
}{
Start_block();
//Sequentially notify PDU off then switch off S/S
//This maybe non-instictive order is due to an ICU bug that
//screws things up when the ICU tries to get HK from a switched off S/S
//
//LOU
Hifi_HIFI_notify_PDU_status("ON","OFF","ON","ON","ON","ON");
//HifiIltEgse_PDU_switch_off($BBID,"LO_Prime");
//HifiIltEgse_PDU_switch_off($BBID,"LO_Red");
//WBS-H
Hifi_HIFI_notify_PDU_status("ON","OFF","ON","OFF","ON","ON");
//HifiIltEgse_PDU_switch_off($BBID,"WBS_H");
//WBS-V
Hifi_HIFI_notify_PDU_status("ON","OFF","OFF","OFF","ON","ON");
//HifiIltEgse_PDU_switch_off($BBID,"WBS_V");
//HRS-H
Hifi_HIFI_notify_PDU_status("ON","OFF","OFF","OFF","ON","OFF");
//HifiIltEgse_PDU_switch_off($BBID,"HRS_H");
//HRS-V
Hifi_HIFI_notify_PDU_status("ON","OFF","ON","OFF","OFF","OFF");
//HifiIltEgse_PDU_switch_off($BBID,"HRS_V");
//ICU
Hifi_HIFI_notify_PDU_status("OFF","OFF","OFF","OFF","OFF","OFF");
//HifiIltEgse_PDU_switch_off($BBID,"ICU_Prime");
//HifiIltEgse_PDU_switch_off($BBID,"ICU_Red");
//At that stage, the instrument is idle...
}
//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_temperatures_block_aot();
//Disable checksum FDIR - HIFI-3120
Disable_CRC_FDIR_block_ops();
}
//Reduced version: IVC
//HIFI-COP-7.2-FPU_FT
procedure FPU_FT_IVC_COP_proc_ops {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b","8"]; // HIFI band
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//General parameters in use
string hbb_heater = "ON";
//hot source on/off
string chopper_loop = "CLOSE";
//
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
if(chopper_loop == "OPEN") {
result = ConfigurationReader("name_chopper",["chop_startup_warm"],"0",0.0);
}
double[] cresult_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = cresult_d[0];
//applies to cold LO
Init_MSA_ops(band,chopper_loop,lo_freq,result[0]{0},hbb_heater,prime_or_redundant);
//
//IVC: first with magnets off, then with magnets on - HIFI-3701
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
IVcurve_with_zero_magnet_fm(band);
}
IVcurve_raw_fm(band);
//
}
//Readback of LCU Memory Patch, block
procedure LCU_readback_TPF_maker {
string section = "P" in ["P","R"];
}{
//
//{int, int[]} [] runs = LcuGetMemoryRuns_ops( section);
{int,int[]}[] runs = LcuGetMemoryRuns(section,1);
int runcount = length(runs);
if(runcount != 0) {
for(int i = 0 .. runcount - 1) {
int count = length(runs[i]{1});
Hifi_HIFI_WBS_Zero(runs[i]{0});
Hifi_HIFI_WBS_Zero(count);
}
//Complement the number of TCs sent to reach the fixed TC pattern needed for TPF
int nb_TC_needed = 400;
int remaining_TC = nb_TC_needed - runcount;
mois_comment("The following " + remaining_TC + " TCs are dummy repetition of the first memory dump command");
//
for(int ii = 1 .. remaining_TC) {
Hifi_HIFI_WBS_Zero(runs[0]{0});
Hifi_HIFI_WBS_Zero(length(runs[0]{1}));
}
}
}
//Load and boot new OBSW from rescue, block
block Load_boot_block_ops HIFI 7929 {
}{
//
mois_step("Construct the OBSW copy");
mois_spacon("Use the OBSM or OBS-loader to prepare the load_mem TC list to build the new version of the OBSW that is to be loaded and started");
//
mois_step("Upload the OBSW copy to DM");
mois_spacon("Use the OBSM or OBS-loader to run the TC list previously prepared to load the new version of the OBSW");
//
mois_step("Run the load boot TC");
Hifi_HIFI_load_boot();
delay(1);
//The new OBSW should be booted
mois_tmcheck("Check that the new OBSW release numbers have been updated (HI_SW_Version, HI_SW_Revision and HI_SW_Patch)");
//
mois_comment("Assign obsid number to procedure execution");
mois_spacon("In the following command, the second parameter (OBS_ID) shall be replaced by a Formal Parameter value according to the list provided by the instrument ICC.");
Hifi_HIFI_Set_OBS_ID($BBID,$OBSID);
//
//Do we want to copy the new image onto the EEPROM ?
//TC for this: Hifi_HIFI_eeprom_write -> decided to rather prepare a dedicated procedure for this.
}
// upload of memory patch table, block
//Prime/Redundant is handled with the CUS table
block LcuMemoryPatchUpload_fm HIFI 3902 {
}{
Start_block();
string section = GetLcuSection();
{int,int[]}[] runs = LcuGetMemoryRuns(section,100);
int runcount = length(runs);
for(int i = 0 .. runcount - 1) {
{int}[] par = [];
int[] values = runs[i]{1};
int count = length(values);
for(int j = 0 .. count - 1) {
par[j] = {values[j]};
}
int crc = checksum("short",values);
Hifi_HIFI_load_LCU(runs[i]{0},count,par,crc);
delay(2);
}
}
// Very Short Performance Test, procedure
// Assumes LO is stabilized, in nominal mode, and instrument is ready to be configured
// Also assumes backends are ready
// This is to be used in cold context
procedure HIFI_VSPT_proc {
string band = "1a"; // HIFI band
double lo_freq = 500.0; //LO frequency
string mixer_polarization = "H" in ["H","V","B"]; //Polarization: H, V or Both
string backend_code = "WBS" in ["WBS","HRS"]; //The backend to be used for magnet tuning
string chop_loop = "CLOSE"; //The chopper loop status
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total integration time in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string mixer_for_tuning = "H" in ["H","V","B"]; //Polarization: H, V or both
}{
//
//Configure FPU
//The chopper will look at rest position per default
//
if(mixer_polarization == "H") {
if(mixer_for_tuning == "V") {
error("V mixer cannot be used for tuning since only mixer H was selected.");
}
if(band == "0") {
Band0_hbb_on_fm(band,chop_loop);
} else {
Init_MSA_H_fm(band,chop_loop,lo_freq);
}
}
if(mixer_polarization == "V") {
if(mixer_for_tuning == "H" || mixer_for_tuning == "B") {
error("H mixer cannot be used for tuning since only mixer V was selected.");
}
if(band == "0") {
Band0_hbb_on_fm(band,chop_loop);
} else {
Init_MSA_V_fm(band,chop_loop,lo_freq);
}
}
if(mixer_polarization == "B") {
if(band == "0") {
Band0_hbb_on_fm(band,chop_loop);
} else {
Init_MSA_fm(band,chop_loop,lo_freq,"ON");
}
}
//
//Set-up LO at new frequency and performs tuning at that frequency.
//Assumes the band was already switched on prior to the VSPT.
//Also assumes we are in nominal mode.
LO_tuning_w_mixerchoice_block_fm(band,lo_freq,mixer_for_tuning);
//
//Magnet tuning: only up to band 5 since band6-7 have no magnets
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
{double,string}[] result_d = ConfigurationReader("name_configwbs",["tune_target_magnet"],band,lo_freq);
int tune_target_magnet = iround(result_d[0]{0});
Magnet_tuning_block_fm(band,lo_freq,backend_code,tune_target_magnet);
}
//
//Spectrometer attenuator tuning: should be done on Hot source
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_hot_ang");
//
//WBS calibration and backend tuning
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
WBS_tune_proc_fm(band);
}
if(backend == "hrs" || backend == "both") {
HRS_tune_block_fm(band);
}
//
//Configure spectrometers after tuning
int[] res = Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
//HotCold measurement
Hot_cold(band,hrs_mode,backend,res[0] * res[1],"tp",0,0);
//
}
//HIFI-COP-3-Tsys + Vecscan merged with M1/M2 control
procedure Tsys_Vecscan_M1_COP_proc_ops {
string band = "1a" in ["1a","5a","5b","7b"]; // HIFI band
int integ_time = 4;
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
int n_wbs1 = 0;
int n_hrs_trans = 0;
string chopmode = "slowchop";
}{
//
LCU_switchon_proc_fm(band);
//Wait an extra delay of 1 min for short term stabilization
delay(60);
//
HRS_config_block_fm(band,hrs_mode);
//
int[] res = [0,0];
res = Configure_Spectrometer_hc_slow_chop_proc_fm(band,integ_time * 2,hrs_mode,backend);
int total_time = res[0] * res[1];
//
//Get the list of frequencies to be used for the scan
string tab = "config_surveytsys.config";
double bandnb = GetBandCode(band);
double lofreqlow = dlookup(tab,"" + iceil(bandnb),"lofreqlow");
double lofreqhigh = dlookup(tab,"" + iceil(bandnb),"lofreqhigh");
double lofreqstep = dlookup(tab,"" + iceil(bandnb),"lofreqstep");
//
double current_LO = lofreqlow;
bool endreached = false;
//Loop on key frequencies per LO band
while(current_LO <= lofreqhigh && endreached == false) {
//
Init_MSA_HBB_fm(band,"CLOSE",current_LO,"ON");
//Get nominal M1V
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,["m1_v"],band,current_LO);
double m1v_nom = result[0]{0};
//
double[] m1v_array = [];
double[] m2v_array = [];
int nb_m1v = 0;
debug_print(current_LO);
//Band 1a: 22/04/10: array of M1V above 7.45
if(band == "1a") {
//double m1v = 7.45;
m1v_array[0] = 7.45;
m1v_array[1] = 7.7;
m1v_array[2] = 7.95;
m1v_array[3] = 8.2;
nb_m1v = 3;
}
if(band == "5a" || band == "5b") {
double m1v_min = m1v_nom - 0.2;
m1v_array[0] = m1v_min;
m1v_array[1] = m1v_nom;
double m1v_current = m1v_nom + 0.5;
nb_m1v = 1;
double m1v_clipp = -4.0;
if(band == "5b") {
m1v_clipp = -5.0;
}
while(m1v_current <= m1v_clipp) {
m1v_array[nb_m1v + 1] = m1v_current;
m1v_current = m1v_current + 0.5;
nb_m1v = nb_m1v + 1;
}
//Ensure the last step is at the clipped value
if(abs(m1v_current - 0.5 - m1v_clipp) > 0.1) {
m1v_array[nb_m1v + 1] = m1v_clipp;
nb_m1v = nb_m1v + 1;
}
}
//Band 7b: two pairs of M1V/M2V
if(band == "7b") {
m1v_array[0] = -7.8;
m1v_array[1] = -7.8;
m2v_array[0] = -12.0;
m2v_array[1] = -11.5;
nb_m1v = 1;
}
//Loop on M1V in m1v_array
for(int j = 0 .. nb_m1v) {
debug_print(m1v_array[j]);
bool first_tuning = true;
if(j > 1) {
first_tuning = false;
}
//For 7b, we need M1 and M2
if(band == "7b") {
debug_print(m2v_array[j]);
LO_tuning_Vecscan_M1M2_block_fm(band,current_LO,m1v_array[j],m2v_array[j]);
} else {
LO_tuning_Vecscan_M1_block_fm(band,current_LO,m1v_array[j]);
}
WBS_calib_fm(band);
//Does a magnet tuning: only up to band 5 since band6-7 have no magnets
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
if(first_tuning) {
Magnet_tuning_block_fm(band,current_LO,"HRS",40);
}
//for first freq of each LO band, deflux heater
if(current_LO == lofreqlow && (band != "5a" && band != "5b")) {
//Deflux heaters
Heater_cop(band);
//Second magnet tuning
Magnet_tuning_block_fm(band,current_LO,"HRS",40);
}
}
if(first_tuning) {
WBS_tune_proc_fm(band);
HRS_tune_block_fm(band);
}
//
Hot_cold(band,hrs_mode,backend,total_time,chopmode,n_wbs1,n_hrs_trans);
//
//Check last LO freq done
if(current_LO == lofreqhigh && endreached == false) {
endreached = true;
}
}
//Increase LO freq: truncate if step too high
current_LO = current_LO + lofreqstep;
if(current_LO > lofreqhigh && endreached == false) {
current_LO = lofreqhigh;
}
}
}
//Procedure to translate old band name into new convention
string procedure Translate_band_name {
string band = "1a"; //"OLD" band naming
}{
//Translate band name
string band_new = "1a";
if(band == "1a") {
//Band 1a
band_new = "1a";
}
if(band == "1b") {
//Band 1b
band_new = "1b";
}
if(band == "2a") {
//Band 2a
band_new = "2a";
}
if(band == "2b") {
//Band 2b
band_new = "2b";
}
if(band == "3a") {
//Band 3a
band_new = "3a";
}
if(band == "3b") {
//Band 3b
band_new = "3b";
}
if(band == "4a") {
//Band 4a
band_new = "4a";
}
if(band == "4b") {
//Band 4b
band_new = "4b";
}
if(band == "5a") {
//Band 5a
band_new = "5a";
}
if(band == "5b") {
//Band 5b
band_new = "5b";
}
if(band == "6a") {
//Band 6a
band_new = "6a";
}
if(band == "6b") {
//Band 6b
band_new = "6b";
}
if(band == "7a") {
//Band 7a
band_new = "7a";
}
if(band == "7b") {
//Band 7b
band_new = "7b";
}
return band_new;
}
// 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;
}
// 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;
}
//Readback of LCU Memory Patch, block
block LcuMemoryPatchReadback_fm HIFI 3903 {
}{
Start_block();
string section = GetLcuSection();
{int,int[]}[] runs = LcuGetMemoryRuns(section,498);
int runcount = length(runs);
for(int i = 0 .. runcount - 1) {
int count = length(runs[i]{1});
Hifi_HIFI_dump_memory("LCU",runs[i]{0},count);
// delay( iceil( double( count ) *.003 ) ); // 3 msec per word readout
// Workaround
delay(2 + iceil(double(count) * 0.0030));
// 3 msec per word readout
}
}
// thermal tests, fast: this is the quick health check
// Follows description of FPSS-01204
block Thermal_fast_fm HIFI 3281 {
string band = "1a"; // HIFI band
double lo_freq = 522.0; //LO frequency
}{
//Start_block();
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["band"],band,lo_freq);
int band_nb = iround(result_d[0]{0});
//
//Get Targetted values for magnet, mixer bias, heater time and diplexer
double[] cresult_d = CalibrationReader("name_configthermal",["dipl_h","magn_h","mbias_h","heat_h","dipl_v","magn_v","mbias_v","heat_v"],band,0.0);
double target_dipl_h = cresult_d[0];
double target_magn_h = cresult_d[1];
double target_mbias_h = cresult_d[2];
double target_heat_h = cresult_d[3];
double target_dipl_v = cresult_d[4];
double target_magn_v = cresult_d[5];
double target_mbias_v = cresult_d[6];
double target_heat_v = cresult_d[7];
//
//Read SIF
cresult_d = CalibrationReader("name_configthermal",["sif1hv","sif1hc","sif2hv","sif2hc","sif3hv","sif3hc"],band,0.0);
double volt_H_SIF_1 = cresult_d[0];
double curr_H_SIF_1 = cresult_d[1];
double volt_H_SIF_2 = cresult_d[2];
double curr_H_SIF_2 = cresult_d[3];
double volt_H_SIF_3 = cresult_d[4];
double curr_H_SIF_3 = cresult_d[5];
//
cresult_d = CalibrationReader("name_configthermal",["sif1vv","sif1vc","sif2vv","sif2vc","sif3vv","sif3vc"],band,0.0);
double volt_V_SIF_1 = cresult_d[0];
double curr_V_SIF_1 = cresult_d[1];
double volt_V_SIF_2 = cresult_d[2];
double curr_V_SIF_2 = cresult_d[3];
double volt_V_SIF_3 = cresult_d[4];
double curr_V_SIF_3 = cresult_d[5];
//
//Read FIF: these are the nominal values
cresult_d = CalibrationReader("name_configthermal",["fif1v","fif1c","fif2v","fif2c"],band,0.0);
double volt_H_FIF_1 = cresult_d[0];
double curr_H_FIF_1 = cresult_d[1];
double volt_H_FIF_2 = cresult_d[2];
double curr_H_FIF_2 = cresult_d[3];
//
double volt_V_FIF_1 = cresult_d[0];
double curr_V_FIF_1 = cresult_d[1];
double volt_V_FIF_2 = cresult_d[2];
double curr_V_FIF_2 = cresult_d[3];
//
//Get chopper settings
string chop_sine_s = "ON";
string chop_loop = "CLOSE";
result_d = ConfigurationReader("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2"],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});
//
result_d = ConfigurationReader("name_confilfpu",["calibrator_current_on"],band,lo_freq);
double calibcurrent = result_d[0]{0};
double bias_H = target_mbias_h;
double magnetcurrent_H = target_magn_h;
double diplex_H = target_dipl_h;
double bias_V = target_mbias_v;
double magnetcurrent_V = target_magn_v;
double diplex_V = target_dipl_v;
result_d = ConfigurationReader("name_confilfpu",["chop_cold"],band,lo_freq);
double chopper = result_d[0]{0};
chopper = Check_Chopper_Prime_Redundant(chopper);
//
//Get diplexer codes
if(band_nb <= 2 || band_nb == 5) {
int diplex_h_ctrl_mode = 0;
int 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});
}
//
//1. Switch on diplexer, SIF, FIF, magnets and mixer bias
//
//Send command to FPU and wait 25 min.
HIFI_Configure_FCU_proc_fm(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);
delay(1500);
//
//2. Check heater current effect on temperature: Let current ON
// during the standard deflux time.
//We will bias the junction at low bias to check when
//the heater effect is effective
result_d = ConfigurationReader("name_confilfpu",["bias_very_low_h","bias_very_low_v"],band,lo_freq);
bias_H = result_d[0]{0};
bias_V = result_d[1]{0};
Mixerbias(bias_H,bias_V);
//
//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);
//
//Get time during which one wants to send the pulse
double max_heater_time_h = target_heat_h * 1000.0;
//in msec
double max_heater_time_v = target_heat_v * 1000.0;
//in msec
//Start to send the pulse
//H-polar first
Hifi_HIFI_HF_CH1_DHTR_C($BBID,max_heater_time_h);
delay(iceil(max_heater_time_h / 1000.0) + 1);
//V-polar then
Hifi_HIFI_HF_CV1_DHTR_C($BBID,max_heater_time_v);
delay(iceil(max_heater_time_v / 1000.0) + 1);
//
//3. Heater back to 0: achieved automatically after the above is elapsed.
//Extra delay to cool down in band 0 before switch to next band
Band0_chopper_on_proc_fm("0","CLOSE");
//Wait another 25 minutes
delay(1500);
//
}
// Initialisation of FPU, block with only V-MSA in use
// It is only for cold context !
block Init_MSA_V_fm HIFI 3208 {
string band = "1a";
string chop_loop = "CLOSE";
double lo_freq = 522.0; //LO frequency
}{
Start_block();
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["band"],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;
//
result_d = ConfigurationReaderWarm("name_confilfpu",["fif1v_h","fif1c_h","fif2v_h","fif2c_h","sif1v_h","sif1c_h","sif2v_h","sif2c_h","sif3v_h","sif3c_h"],"0",0.0);
//
double volt_H_FIF_1 = result_d[0]{0};
double curr_H_FIF_1 = result_d[1]{0};
double volt_H_FIF_2 = result_d[2]{0};
double curr_H_FIF_2 = result_d[3]{0};
//
double volt_H_SIF_1 = result_d[4]{0};
double curr_H_SIF_1 = result_d[5]{0};
double volt_H_SIF_2 = result_d[6]{0};
double curr_H_SIF_2 = result_d[7]{0};
double volt_H_SIF_3 = result_d[8]{0};
double curr_H_SIF_3 = result_d[9]{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_on"],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};
//
//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,0.0);
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.
//chopper = Check_Chopper_Prime_Redundant(chopper);
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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,lo_freq);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
//In case of band 6 or 7, bias have been set to 4mV. Now set to nominal
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq);
Mixerbias(result[0]{0},result[1]{0});
}
//
//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);
}
//
Hifi_HIFI_non_periodic_hk_FCU();
}
//Shutter rotation during peakup in ILT context, procedure
//Shutter is used to partially blind external BB load
procedure Peakup_shutter_rotation_proc_fm {
string band = "1" in ["1","2","3","4","5","6","7"]; // HIFI band
int position = 1 in [1,9]; //peakup pattern sequence number: from 1 to 9
string peakup_matrix = "centred" in ["centred","offseted","flat"]; //Which brightness distribution to simulate with shutter
}{
//Get number of shutter rotation steps depending on position number
string band_nb = band + "a";
string name_shutter_pos = "name_shutter_pos_centred";
if(peakup_matrix == "offseted") {
name_shutter_pos = "name_shutter_pos_offseted";
}
{double,string}[] result = ConfigurationReader(name_shutter_pos,["shutter_step"],band_nb,double(position));
//If flat distribution is chosen, the shutter should not be moved
int shutter_step = iround(result[0]{0});
if(peakup_matrix == "flat") {
shutter_step = 1;
}
//
//Rotate shutter: number of steps is accounted from open position
//HifiIltEgse_FPU_set_shutter_betw($BBID,shutter_step);
//Fixed delay
result = ConfigurationReader(name_shutter_pos,["shutter_delay"],band_nb,double(position));
delay(iround(result[0]{0}));
//
}
///////////////////////////////////////////////////////////////////////////////
// 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 correct order
int[] widebits = [129,66,36,24];
// [10000001,01000010,00100100,00011000]
int[] lowbits = [192,48,12,3];
// [11000000,00110000,00001100,00000011]
int[] normalbits = [240,15];
// [11110000,00001111]
int[] highbits = [255];
// [11111111]
// 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};
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Single Point - DBS slowChop",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval});
ChopMessages(false,data_time,n_switch_on);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
// Stability test, procedure, case 4
// Measurement of internal cold against external cold
procedure Proc_stability_intcold_extcold {
string band = "1a"; // HIFI band
int n = 100; //Number of load pairs to be measured
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
int integ_time = 4; //Total (co-added) integration time of a phase in sec.
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string chopmode = "slowchop" in ["slowchop","fastchop"]; //Whether to use slowchop or fastchop
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length
}{
//
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_hot_ang");
//Look at HBB
//
//WBS calibration
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
WBS_tune_proc_fm(band);
}
if(backend == "hrs" || backend == "both" || backend == "hrsFast") {
//Configure and tune backends
HRS_config_block_fm(band,hrs_mode);
HRS_tune_block_fm(band);
}
//
//Configure spectrometers integration after tuning: done later
//Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
Stability_intcold_extcold_fm(band,n,integ_time,hrs_mode,backend,chopmode,chop_phase);
//Configure spectrometers integration back to default in tp mode
Configure_Spectrometer_proc_fm(band,4,hrs_mode,backend);
//2 sec. integration
}
//////////////////////////////////////////////////////////////////////////
// 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};
}
// LCU1b configuration and tuning, procedure
procedure LCU1b_config_tune_proc_fm {
string band = "1b"; // HIFI band
double lo_freq = 600.0 in [566.0,633.0]; //LO frequency
double drain_2_factor = 100.0; //Percentage factor of the targetted drain voltage
}{
error("This module is obsolete: use LO_tuning_block_fm instead");
}
//HIFI-COP-7.2-FT: Regular FT during PV and routine for health monitoring
obs HifiEng_HealthMon_FT {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(HealthMon_FT_COP_proc_ops(prime_or_redundant));
// 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) {
// Test execution
HealthMon_FT_COP_proc_ops(prime_or_redundant);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
//Transition mode from standby1 to dissipative1
procedure HifiSetFromStandby_I_IntoDissipative_I {
}{
//
//Clear potential failure mode
Set_LO_Nominal_block_aot();
//
LCU_switch_off_block_aot();
//Will put heaters to 6V
Set_LO_Dissipative_block_aot();
//
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// These scripts allow to perform the FPU Functional
// tests at SS level. They correspond to the procedures
// prepared by PD.
//
// DT - 28 Sep 2004: First draft for QM
// 20 Jul 2005: Update for FM
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Modes: see fm_testmodes.cus
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Associated blocks
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// First part of FPSS FM functional test without spectra, block
// Check that IF amplification is effective (only HK)
procedure FT_FPU_check_IF_nospectra_fm {
string band = "1a";
string context = "warm" in ["warm","cold"]; //Test context: warm or cold
}{
//At that stage, all IFs are ON
//
//Switch OFF FIF
//Get parameters
{double,string}[] result_h = 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,0.0);
if(context == "warm") {
result_h = ConfigurationReaderWarm("name_confilfpu",["band","fif1v_h","fif1c_h","fif2v_h","fif2c_h","sif1v_h","sif1c_h","sif2v_h","sif2c_h","sif3v_h","sif3c_h"],band,0.0);
}
//
int band_nb = iround(result_h[0]{0});
int diplex_h_ctrl_mode = 0;
int diplex_v_ctrl_mode = 0;
//
double volt_H_FIF_1 = 0.075;
double curr_H_FIF_1 = 0.5;
double volt_H_FIF_2 = 0.075;
double curr_H_FIF_2 = 0.5;
//
double volt_H_SIF_1 = result_h[5]{0};
double curr_H_SIF_1 = result_h[6]{0};
double volt_H_SIF_2 = result_h[7]{0};
double curr_H_SIF_2 = result_h[8]{0};
double volt_H_SIF_3 = result_h[9]{0};
double curr_H_SIF_3 = result_h[10]{0};
//
{double,string}[] result_v = ConfigurationReader("name_confilfpu",["fif1v_v","fif1c_v","fif2v_v","fif2c_v","sif1v_v","sif1c_v","sif2v_v","sif2c_v","sif3v_v","sif3c_v"],band,0.0);
if(context == "warm") {
result_v = ConfigurationReaderWarm("name_confilfpu",["fif1v_v","fif1c_v","fif2v_v","fif2c_v","sif1v_v","sif1c_v","sif2v_v","sif2c_v","sif3v_v","sif3c_v"],band,0.0);
}
//
//
double volt_V_FIF_1 = 0.075;
double curr_V_FIF_1 = 0.5;
double volt_V_FIF_2 = 0.075;
double curr_V_FIF_2 = 0.5;
//
double volt_V_SIF_1 = result_v[4]{0};
double curr_V_SIF_1 = result_v[5]{0};
double volt_V_SIF_2 = result_v[6]{0};
double curr_V_SIF_2 = result_v[7]{0};
double volt_V_SIF_3 = result_v[8]{0};
double curr_V_SIF_3 = result_v[9]{0};
//
string chop_sine_s = "ON";
string chop_loop = "CLOSE";
{double,string}[] result = ConfigurationReader("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2","chop_g3","chop_p3","calibrator_current"],band,0.0);
if(context == "warm") {
result = ConfigurationReaderWarm("name_confilfpu",["chop_g1","chop_g2","chop_z1","chop_z2","chop_p2","chop_g3","chop_p3","calibrator_current"],band,0.0);
}
//
int chop_G1 = iround(result[0]{0});
int chop_G2 = iround(result[1]{0});
int chop_Z1 = iround(result[2]{0});
int chop_Z2 = iround(result[3]{0});
int chop_P2 = iround(result[4]{0});
//
//
//
double calibcurrent = result[7]{0};
//
double bias_H = 0.0;
double magnetcurrent_H = 0.0;
double diplex_H = 0.0;
double bias_V = 0.0;
double magnetcurrent_V = 0.0;
double diplex_V = 0.0;
double chopper = 0.0;
//
//
chopper = Check_Chopper_Prime_Redundant(chopper);
HIFI_Configure_FCU_proc_fm(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 = ConfigurationReader("name_delays",["config_fpu_delay"],band,0.0);
int config_fpu_delay = iround(result[0]{0});
delay(config_fpu_delay);
//
//Switch OFF SIF
//
volt_H_SIF_1 = 0.075;
curr_H_SIF_1 = 0.5;
volt_H_SIF_2 = 0.075;
curr_H_SIF_2 = 0.5;
volt_H_SIF_3 = 0.075;
curr_H_SIF_3 = 0.5;
//
volt_V_SIF_1 = 0.075;
curr_V_SIF_1 = 0.5;
volt_V_SIF_2 = 0.075;
curr_V_SIF_2 = 0.5;
volt_V_SIF_3 = 0.075;
curr_V_SIF_3 = 0.5;
//
chopper = Check_Chopper_Prime_Redundant(chopper);
HIFI_Configure_FCU_proc_fm(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);
//
delay(config_fpu_delay);
//
}
// WBS configuration with laser choice, block
// Both polarizations are treated
block WBS_config_w_laser_and_att_block_fm HIFI 3636 {
string band = "1a"; // HIFI band
string laser_H = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-V laser to be set ON
int[] att_h = [7,7,7,7,15]; //User input att. for optimum level H-polar
int[] att_v = [7,7,7,7,15]; //User input att. for optimum level V-polar
}{
//Start_block();
//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 = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
int hwh_heater = iround(result_d[2]{0});
string hwh_latchup_s = result_d[3]{1};
int hwh_att_band4 = att_h[3];
int hwh_att_band3 = att_h[2];
int hwh_att_band2 = att_h[1];
int hwh_att_band1 = att_h[0];
int hwh_att_in = att_h[4];
//
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 = "OFF";
string hwv_laser2_s = "OFF";
if(laser_V == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_V == "Laser2") {
hwv_laser2_s = "ON";
}
int hwv_heater = iround(result_d[2]{0});
string hwv_latchup_s = result_d[3]{1};
int hwv_att_band4 = att_v[3];
int hwv_att_band3 = att_v[2];
int hwv_att_band2 = att_v[1];
int hwv_att_band1 = att_v[0];
int hwv_att_in = att_v[4];
//
//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
//
}
// Needs the chopper in open-loop mode !!
block Chopper_openloop_scan_block_ops HIFI 7694 {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//Hard-coded RAW values for end stops and rest position
int low = 1298;
//This is slightly further the low end-stop
int high = 2548;
//This is slightly further the high end-stop
int zero = 2048;
//This is the zero position
int step = 50;
//
//Go-nogo criteria - taken from FPSS-01046 issue 3
double c0 = -7.71;
double c0_E = 0.2;
double c1 = 8.73;
double c1_E = 0.2;
if(prime_or_redundant == "Red") {
c0 = -8.76;
c0_E = 0.2;
c1 = 7.61;
c1_E = 0.2;
}
//
int chopper_pos = zero;
//Scan from zero to end-stop high
mois_comment("Scanning from 2048 RAW to 2548 RAW");
while(chopper_pos <= high) {
//Prime/Red has no effect on RAW to send, only to the TC name
if(prime_or_redundant == "Prime") {
Hifi_HIFI_P_Chopper_Rot_RAW($BBID,chopper_pos);
//Rotate chopper
} else {
Hifi_HIFI_R_Chopper_Rot_RAW($BBID,chopper_pos);
//Rotate chopper
}
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent value
mois_tmcheck("Check that parameter HF_DPR_CH_ROT is set to " + chopper_pos + " in RAW units");
chopper_pos = chopper_pos + step;
delay(2);
}
//Go-nogo criterion after first scan
mois_tmcheck("Check that parameter HF_APR_CH_ROT is within " + c0 + " +/- " + c0_E + " V. If not procedure needs to be aborted and the HIFI ICC contacted.");
//Scan from end-stop high to end-stop low
mois_comment("Scanning from 2548 RAW to 1298 RAW");
chopper_pos = 2498;
while(chopper_pos >= low) {
//Prime/Red has no effect on RAW to send, only to the TC name
if(prime_or_redundant == "Prime") {
Hifi_HIFI_P_Chopper_Rot_RAW($BBID,chopper_pos);
//Rotate chopper
} else {
Hifi_HIFI_R_Chopper_Rot_RAW($BBID,chopper_pos);
//Rotate chopper
}
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent value
mois_tmcheck("Check that parameter HF_DPR_CH_ROT is set to " + chopper_pos + " in RAW units");
chopper_pos = chopper_pos - step;
delay(2);
}
//Go-nogo criterion after second scan
mois_tmcheck("Check that parameter HF_APR_CH_ROT is within " + c1 + " +/- " + c1_E + " V. If not procedure needs to be aborted and the HIFI ICC contacted.");
//Scan from end-stop low to zero
mois_comment("Scanning from 1298 RAW to 2048 RAW");
chopper_pos = 1348;
while(chopper_pos <= zero) {
//Prime/Red has no effect on RAW to send, only to the TC name
if(prime_or_redundant == "Prime") {
Hifi_HIFI_P_Chopper_Rot_RAW($BBID,chopper_pos);
//Rotate chopper
} else {
Hifi_HIFI_R_Chopper_Rot_RAW($BBID,chopper_pos);
//Rotate chopper
}
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent value
mois_tmcheck("Check that parameter HF_DPR_CH_ROT is set to " + chopper_pos + " in RAW units");
chopper_pos = chopper_pos + step;
delay(2);
}
}
/////////////////////////////////////////////////////////////
// FPU configuration, procedure: is not used at the present time..
procedure Configure_FPU_proc_fm {
string band = "1a"; // HIFI band
double lo_freq = 522.0; //LO frequency
string mixer_polarization = "B" in ["H","V","B"]; //Polarization: H, V, or both (B)
string chop_loop = "CLOSE"; //Chopper loop status
double chop = 0.0; //Chopper position
}{
//Fetch parameters
//H-polar
{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};
//V-polar
result_d = ConfigurationReader("name_confilfpu",["band","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[1]{0};
double curr_V_FIF_1 = result_d[2]{0};
double volt_V_FIF_2 = result_d[3]{0};
double curr_V_FIF_2 = result_d[4]{0};
//
double volt_V_SIF_1 = result_d[5]{0};
double curr_V_SIF_1 = result_d[6]{0};
double volt_V_SIF_2 = result_d[7]{0};
double curr_V_SIF_2 = result_d[8]{0};
double volt_V_SIF_3 = result_d[9]{0};
double curr_V_SIF_3 = result_d[10]{0};
//Set IF according to polarization in use
if(mixer_polarization == "H") {
//Set V-polar to 0
volt_V_FIF_1 = 0.0;
curr_V_FIF_1 = 0.0;
volt_V_FIF_2 = 0.0;
curr_V_FIF_2 = 0.0;
//
volt_V_SIF_1 = 0.0;
curr_V_SIF_1 = 0.0;
volt_V_SIF_2 = 0.0;
curr_V_SIF_2 = 0.0;
volt_V_SIF_3 = 0.0;
curr_V_SIF_3 = 0.0;
//
}
if(mixer_polarization == "V") {
//Set H-polar to 0
volt_H_FIF_1 = 0.0;
curr_H_FIF_1 = 0.0;
volt_H_FIF_2 = 0.0;
curr_H_FIF_2 = 0.0;
//
volt_H_SIF_1 = 0.0;
curr_H_SIF_1 = 0.0;
volt_H_SIF_2 = 0.0;
curr_H_SIF_2 = 0.0;
volt_H_SIF_3 = 0.0;
curr_H_SIF_3 = 0.0;
//
}
//
//Chopper settings
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};
//Freq. dependent bias and magnet settings
result_d = ConfigurationReader("name_confilmix",["norm_bias_h","norm_magn_h","norm_bias_v","norm_magn_v"],band,lo_freq);
double bias_H = result_d[0]{0};
double norm_magnetcurrent_H = result_d[1]{0};
double bias_V = result_d[2]{0};
double norm_magnetcurrent_V = result_d[3]{0};
//Max. magnets for hysteresis
result_d = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,lo_freq);
double magnetcurrent_H = result_d[0]{0};
double 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];
}
//
chop = Check_Chopper_Prime_Redundant(chop);
HIFI_Configure_FCU_proc_fm(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,chop,diplex_H,diplex_V);
//
result_d = ConfigurationReader("name_delays",["config_fpu_delay"],band,lo_freq);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
//In case of band 6 or 7, bias have been set to 4mV. Now set to nominal
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq);
Mixerbias(result[0]{0},result[1]{0});
}
//
//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);
}
//
Hifi_HIFI_non_periodic_hk_FCU();
delay(1);
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 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,true);
//Magnet tuning: use either HRS or WBS, not for bands 1,2,6,7 (SCR-2380)
if(band == "3a" || band == "3b" || band == "4a" || band == "4b" || band == "5a" || band == "5b") {
// 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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Map Load Chop noRef",{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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
// Switch HIFI on, procedure
//
procedure HIFI_global_switch_on_proc_ops {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//Sequentially switches on, then notify PDU
//
//WBS-H
mois_step("Switch ON WBS-H S/S");
PDU_switch_on_block_ops("WBS_H");
mois_comment("Notify PDU status for WBS-H");
HIFI_notify_PDU_status_on_block_ops("ON","OFF","OFF","ON","OFF","OFF","WBSH");
//WBS-V
mois_step("Switch ON WBS-V S/S");
PDU_switch_on_block_ops("WBS_V");
mois_comment("Notify PDU status for WBS-H");
HIFI_notify_PDU_status_on_block_ops("ON","OFF","ON","ON","OFF","OFF","WBSV");
//HRS-H and HRS-V are first powered ON, FT#0 is done, then notify PDU
mois_step("Switch ON HRS-H S/S");
PDU_switch_on_block_ops("HRS_H");
mois_step("Switch ON HRS-V S/S");
PDU_switch_on_block_ops("HRS_V");
//HRS FT#0 and special HK handling for this
mois_step("HRS start-up");
mois_comment("House-keeping for HRS-H and HRS-V is de-selected");
Switch_HK_block_ops("ON","ON","ON","ON","OFF","OFF");
mois_comment("Notify PDU status for HRS-H and HRS-V");
HIFI_notify_PDU_status_on_block_ops("ON","OFF","ON","ON","OFF","ON","HRSH");
HIFI_notify_PDU_status_on_block_ops("ON","OFF","ON","ON","ON","ON","HRSV");
HRS_functional_test_No_0_block_ops();
mois_comment("House-keeping for HRS-H and HRS-V is selected again");
Switch_HK_block_ops("ON","ON","ON","ON","ON","ON");
mois_comment("Initial configuration of HRS blocks and LO");
HRS_standby_block_ops("0",["wb","wb"]);
//LOU
mois_step("Switch ON LO S/S");
string lo_subsys = "LO_Prime";
if(prime_or_redundant == "Red") {
lo_subsys = "LO_Red";
}
PDU_switch_on_block_ops(lo_subsys);
mois_comment("Notify PDU status for LCU");
HIFI_notify_PDU_status_on_block_ops("ON","ON","ON","ON","ON","ON","LCU");
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Spectral Scan - Frequency Switch Ref",{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,imin(data_time,data_time_off));
{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);
// Final message to check for both polarizations
PolarizationMessage(hr1{0},hr2{0},wb1{0},wb2{0});
// 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}};
}
// 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;
// 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) {
i_phase = (state[2] + 1) % 2;
// 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);
}
// Other frequencies
// Reset group counter
i_group = 1;
while(i_group <= grouplen - 1) {
// retune
runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen];
HIFIChangeFreqFsw(band,runningfreq,freq_throw);
if(i_group == 1) {
if(isinvalid || islong) {
HIFIConfigureFSwitchIntegration(data_time_off,n_per_off,band,reffreq,backendreadoutparms);
islong = false;
isinvalid = false;
}
}
HIFIFSwitchOnIntegration(data_time_off,n_per_off,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 && 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,false,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;
while(i_group <= grouplen - 1) {
// retune
runningfreq = freqgrid[grouporder[i_phase][i_group] + i_freqcycles * grouplen];
HIFIChangeFreqFsw(band,runningfreq,freq_throw);
if(i_group == 1) {
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);
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,false,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,false,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();
}
}
}
// 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];
}
//Set LCU3a back to standby status, procedure
procedure LCU3a_standby_proc_fm {
string band = "3a"; // HIFI band
double lo_freq = 810.0 in [807.0,848.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
// 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.");
}
}
//TM to control FDIR on LOU temp.
block LO_Temp_FDIR_block_fm HIFI 3952 {
string activate = "ON" in ["ON","OFF"]; //Whether FDIR is activated or not
double tmin = 123.0; //Min threshold
double tmax = 145.0; //Max threshold
int nbreach = 10; //Number of breach
}{
Start_block();
if(activate == "OFF") {
Hifi_HIFI_LOU_T_check_off();
} else {
Hifi_HIFI_LOU_T_check_on(nbreach,tmax,tmin);
}
delay(1);
//
}
// 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};
}
//Write EEPROM , block
block Write_EEPROM_block_ops HIFI 7930 {
}{
mois_step("Write on EEPROM partition of relevance");
mois_spacon("Ask the HIFI support on which partition on the EEPROM the software must be written (either 1 or 2). The answer to this question corresponds to the formal parameter HP228197 (= hifi_HIF_partition_ID) of the next command.");
mois_spacon("Similarly, ask the HIFI support which end address should be used (in consistency with applicable issue of SRON_U/HIFI/PR/2007-007). The answer to this question corresponds to the formal parameter HP005197 (= hifi_OBS_mem_end) of the next command.");
//
int hifi_OBS_mem_end = 0x185c1;
//this is applicable to OBS5.8.1.
int hifi_HIF_partition_ID = 1;
int hifi_HIF_Npages_to_skip = 0;
Hifi_HIFI_eeprom_write(hifi_OBS_mem_end,hifi_HIF_partition_ID,hifi_HIF_Npages_to_skip,[]);
delay(1);
mois_spacon("Please log the partition and end address that were used, together with the OBSW version");
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// FM CUS scripts to assess various instrument settling
// times (CAL UC-1.1.2)
//
// DT - 27 Oct 2005: first draft based on CAL UC doc.
//
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//modes: see fm_testmodes.cus
///////////////////////////////////
// Procedures
///////////////////////////////////
// Chopper Response time with user input choice on angle, block
block Chopper_Response_time_EXPERT_block_fm HIFI 3686 {
double targetAngle = 0.1; // angle to move to
int milliSecSample = 3; // interval between samples
int samplesBefore = 30 in [0,50];
int samplesAfter = 100 in [0,1000];
}{
Start_block();
//
targetAngle = Check_Chopper_Prime_Redundant(targetAngle);
HIFI_Chopper_scan_fast_proc_fm(milliSecSample,targetAngle,samplesBefore,samplesAfter);
//
// delay calculation TBC
int millisecondsUsed = 500 + milliSecSample * (samplesBefore + samplesAfter + 1);
delay(iceil(0.0010 * double(millisecondsUsed)));
//
}
//HIFI-COP-X-IF-FBk-Cal - goes into dissipative mode
obs HifiEng_IF_FBk_Cal_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string chopcase = "dbs" in ["dbs","csa","lsw"]; //chopper delta considered
int testtime = 3600; //total test time in seconds
}{
//General parameters in use
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
double[] result_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = result_d[0];
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
//Avoid high data-rates
if(testtime % 3 == 0 && testtime % 4 == 0) {
testtime = testtime + 4;
}
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"start");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(IF_FBk_Cal_COP_proc_ops(band,lo_freq,hrs_mode,testtime,backend,chopcase));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
IF_FBk_Cal_COP_proc_ops(band,lo_freq,hrs_mode,testtime,backend,chopcase);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
// Read addresses and get checksum for a given code category
// Returns:
// - the array of address_start, address_length
// - the full checksum of all concatenated address areas
// - the full length of all concatenated address areas
//
{{int,int}[],int,int} procedure LcuGetCodeAddress_ops {
string code_category = "Safe" in ["Safe","Critical","Unused"]; //safe, critical or unused
}{
string tab = "LcuAddressCode" + code_category + "_R.config";
{int,int}[] pairs = [];
int total_length = 0;
int total_crc = 0;
int total = table_size(tab);
//Get inputs for band 1a - loop on location types
for(int line = 1 .. total) {
int add_S = ilookup(tab,"" + line,"a1S");
int add_L = ilookup(tab,"" + line,"a1L");
pairs[line - 1] = {add_S,add_L};
total_crc = total_crc + ilookup(tab,"" + line,"crc");
total_length = total_length + add_L;
}
//Complement with zeroes until getting to 48 pairs
int hifi_NStep = 48;
for(int line2 = total + 1 .. hifi_NStep) {
add_S = 0;
add_L = 0;
pairs[line2 - 1] = {add_S,add_L};
}
//Wrap-around CRC
total_crc = total_crc % (0xffff + 1);
//
return {pairs,total_crc,total_length};
}
//Contingency for LOU temp FDIR modification
mode HifiManCmd_LOU_FDIR_disable {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to disable the FDIR on limits for LOU operational temperatures");
//StartMode_block_ops();
//
mois_spacon("Verify that HM122190 (HI_auto_LOU_S) is ON");
mois_step("Disable FDIR");
Disable_LO_FDIR_temperatures_block_mois();
//
mois_spacon("Verify that HM122190 (HI_auto_LOU_S) is OFF");
StopMode_block_mois();
// -> to issue last obsd/bbid
}
// Needs the chopper in open-loop mode !!
block Chopper_openloop_scan_block_fm HIFI 3694 {
int scan_portion = 1 in [1,3]; //indicates which part of scans is to be done
}{
//Start_block ();
//Hard-coded RAW values for end stops and rest position
int low = 1298;
//This is slightly further the low end-stop
int high = 2548;
//This is slightly further the high end-stop
int zero = 2048;
//This is the zero position
int step = 50;
//
int chopper_pos = zero;
//Scan from zero to end-stop high
while(chopper_pos <= high) {
if(scan_portion == 1) {
HIFI_CPR_Chopper_Rot_RAW_proc_fm(chopper_pos);
//Rotate chopper
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent value
delay(2);
}
chopper_pos = chopper_pos + step;
}
//Scan from end-stop high to end-stop low
chopper_pos = high - step;
while(chopper_pos >= low) {
if(scan_portion == 2) {
HIFI_CPR_Chopper_Rot_RAW_proc_fm(chopper_pos);
//Rotate chopper
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent value
delay(2);
}
chopper_pos = chopper_pos - step;
}
//Scan from end-stop low to zero
chopper_pos = low + step;
while(chopper_pos <= zero) {
if(scan_portion == 3) {
HIFI_CPR_Chopper_Rot_RAW_proc_fm(chopper_pos);
//Rotate chopper
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent value
delay(2);
}
chopper_pos = chopper_pos + step;
}
}
// 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);
}
}
//Procedure checking the consistency of slow chop spectroscopy
//parameters to be sent to configuration command.
bool procedure Check_slow_chop_parameters_proc {
int n_wbs_start = 4; //Nb of frames
int r_hrs = 1; //Nb of HRS readout per WBS readout
int n_wbs_integr = 1; //Number of wbs readout packetized per WBS frame
int n_hrs_integr = 1; //Number of hrs readout packetized per HRS frame
int del_hrs = 5; //Delay before starting HRS integration
int del_wbs = 5; //Delay before starting WBS integration
int t_acc_wbs = 4005; //Duration of WBS frame
int t_acc_hrs = 1950; //Duration of HRS frame
int wbsh_offset1 = 0;
int wbsh_width1 = 2048;
int wbsh_offset2 = 2048;
int wbsh_width2 = 2048;
int wbsh_offset3 = 4096;
int wbsh_width3 = 2048;
int wbsh_offset4 = 6144;
int wbsh_width4 = 2048;
int wbsv_offset1 = 0;
int wbsv_width1 = 2048;
int wbsv_offset2 = 2048;
int wbsv_width2 = 2048;
int wbsv_offset3 = 4096;
int wbsv_width3 = 2048;
int wbsv_offset4 = 6144;
int wbsv_width4 = 2048;
int hrs_rshift = 0; //HRS bit shift
int wbs_rshift = 0; //WBS bit shift
int hrsh_sel = 255; //HRS-H band selection
int hrsv_sel = 255; //HRS-V band selection
string wbs_packing = "24_bits_format";
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,wb5
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
error("Procedure Check_slow_chop_parameters_proc is not used anymore.");
return false;
}
// Standing wave study for FSW model
//HIFI-COP-X-StWv-FSW
obs HifiEng_StWv_FSW_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(StWv_FSW_COP_proc_ops(band));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
StWv_FSW_COP_proc_ops(band);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
//HIFI-COP-1.2-LO_FT: for MTL in routine: uses single TM page TC
procedure LO_FT_COP_proc_ops {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_comment("Start of HIFI LO Functional Test for band " + band);
mois_comment("Please check that instrument was switched on with the " + prime_or_redundant + " unit");
mois_tmcheck("Check content of AND LCU_temperatures_with HIFI expert.");
//General parameters in use
string multiplier = "ALL";
int operation_delay = 0;
//
double[] cresult_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = cresult_d[0];
//applies to cold LO
//
mois_step("Init MSA");
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
Init_MSA_ops(band,"CLOSE",lo_freq,result[0]{0},"ON",prime_or_redundant);
//
//First switch off the band.
LCU_switch_off_block_fm();
mois_tmcheck("Check that parameter HL_Channel_S is OFF");
//
mois_step("Measure LCU IV curve");
Measure_LCU_IV_proc_fm(band,multiplier,operation_delay);
//
//Switch on with safe Vd2
mois_step("Switch on LO band");
LCU_switchon_proc_fm(band);
mois_tmcheck("Check that parameter HL_MODE_S is normal");
mois_tmcheck("Check that parameter HL_Channel_S is " + band);
//
mois_step("LO SFT");
//This will switch on the chain again
LO_SFT_proc_ops(band,prime_or_redundant);
//
mois_tmcheck("Check whether parameter HL_error_word_S has been FAULT at any time of the procedure. Communicate occurences to HIFI expert.");
mois_tmcheck("Check content of AND LCU_status2 and LCU_" + band + " with HIFI expert.");
}
// Third part of FPSS FM functional test, block
// Magnet scan fine, around expected optimal magnets
// This differs from Magnet_scan_fine which scans over
// the whole range.
block FT_FPU_magnet_tune_fine_fm HIFI 3802 {
string band = "1a";
double magnet_current_h = -5.7; //Central magnet current H
double magnet_current_v = -9.4; //Central magnet current H
double step_current = 0.1; //Current increment in mA
int step_number = 10; //Number of steps
int integ_time = 4; //Integation time in seconds
double lo_freq = 500.0; //LO frequency
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//Get nominal biases and magnets
{double,string}[] result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq);
double bias_h = result[0]{0};
double bias_v = result[1]{0};
//
//H polar
double magnet_min_h = magnet_current_h - step_current * double(step_number) / 2.0;
double magnet_max_h = magnet_current_h + step_current * double(step_number) / 2.0;
//V polar
double magnet_min_v = magnet_current_v - step_current * double(step_number) / 2.0;
double magnet_max_v = magnet_current_v + step_current * double(step_number) / 2.0;
//
double magnet_min = max(magnet_min_h,magnet_min_h);
double magnet_max = min(magnet_max_h,magnet_max_h);
//
double step_duration = 0.1;
int steps = 0;
int steps_done = 0;
int max_per_command = 40;
//
int steps_wanted = step_number;
//
double step = Stepsize(magnet_min,magnet_max,steps_wanted,"hifi_HIF_mx_mg_step_C");
double margin = Stepmargin(magnet_min,magnet_max,"hifi_HIF_mx_mg_step_C");
steps_wanted = 1 + iceil((magnet_max - magnet_min) / step);
// force the last portion to less than max_per_command
if(max_per_command * (steps_wanted / max_per_command) == steps_wanted) {
steps_wanted = steps_wanted - 1;
}
//
//Set magnet to maximum to avoid hysteresis
result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,0.0);
Hifi_HIFI_CH1_MX_MG_C($BBID,result[0]{0});
Hifi_HIFI_CV1_MX_MG_C($BBID,result[1]{0});
delay(2);
//
magnet_current_h = magnet_min_h;
magnet_current_v = magnet_min_v;
while(steps_done < steps_wanted) {
steps = steps_wanted - steps_done;
if(steps > max_per_command) {
steps = max_per_command;
}
magnet_current_h = magnet_min_h + double(steps_done) * step;
magnet_current_v = magnet_min_v + double(steps_done) * step;
Hifi_HIFI_FCU_parameter_scan($BBID,1,1,step_duration,bias_h,bias_v,0.0,magnet_current_h,magnet_current_v,0.0);
delay(2);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
steps_done = steps_done + 1;
}
}
/////////////////////////////////////////////////////////////////
// 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,"dbs");
int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0);
// 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;
}
// Additional constraint of compatibility of group size with load period
int loadperiod = LoadPeriod(band,reffreq,effResolution{1});
// 80% margin
int periodlimit = loadperiod * 4 / 5;
// elements of cycle - compute cycle duration
int tunedelay = LOSettlingTime(band,reffreq / 1000.0,false,true);
int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,effResolution{0},data_time_guess,backendreadoutparms));
int perfreqtime = 2 * (2 * data_time_guess * n_switch_on_guess + tunedelay);
int cycle = perfreqtime * n_freq_point_guess + loadlength;
if(cycle > periodlimit) {
n_freq_point_guess = imax((periodlimit - loadlength) / perfreqtime,1);
}
int n_freq_point_range = 1 - n_freq_point_guess;
if(n_freq_point_range == 0) {
n_freq_point_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;
}
//HIFI HK control, block
block Switch_HK_block_ops HIFI 7605 {
string hk_FCU = "ON" in ["ON","OFF"]; //Status of FCU HK
string hk_LCU = "ON" in ["ON","OFF"]; //Status of LCU HK
string hk_WBSV = "ON" in ["ON","OFF"]; //Status of WBSV HK
string hk_WBSH = "ON" in ["ON","OFF"]; //Status of WBSH HK
string hk_HRSV = "ON" in ["ON","OFF"]; //Status of HRSV HK
string hk_HRSH = "ON" in ["ON","OFF"]; //Status of HRSH HK
}{
StartBlock_ops();
//Get applicable HK rate
{double,string}[] result_d = ConfigurationReader("name_delays",["hk_rate"],"0",0.0);
string hk_rate = result_d[0]{1};
Hifi_HIFI_Housekeeping_on(hk_rate,hk_FCU,hk_LCU,hk_WBSV,hk_WBSH,hk_HRSV,hk_HRSH);
delay(1);
}
// 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);
}
// Repeated COMBs (every comb takes 2s)
procedure Multiple_Comb_COP_proc_ops {
int nb_comb = 10; //The number of COMBs to integrate in a row
}{
// Placeholder arguments
string band = "4a";
// HIFI band (needed to estimate stabilization)
double lo_freq = 978200.0;
// LO frequency
//
// Initial normal comb for reference and zero
WBS_Zero_Comb(band,lo_freq);
//inputs are placeholders
//
// Long term comb measurement
WBS_Multi_Comb(band,lo_freq,nb_comb);
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
/////////////////////////////////////////////////////////////////
// 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,"lo_frequency");
// 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};
}
//Chopper health check test #1 of chopper during open loop, mode
mode HifiManCmd_Chopper_openloop_set_health_check {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_tmcheck("The instrument should be in Standby I mode in open loop context for this test");
//It is done after chopper has been switched on in open loop
mois_tmcheck("The instrument must have been switched on with its " + prime_or_redundant + " electronics");
mois_tmcheck("Check that parameter HF_DPR_CHLOOP_S is set to OPEN");
mois_tmcheck("Check that parameter HF_DPR_CHSINE_S is set to ON");
//
mois_comment("Performing part one of HIFI internal chopper health check");
StartMode_block_ops();
//Prepare LVDT readout check
double c0 = -1.09;
double err_C0 = 0.2;
double c1 = 1.58;
double err_C1 = 0.08;
double err_C0_2 = 0.04;
if(prime_or_redundant == "Red") {
c0 = -2.315;
err_C0 = 0.2;
c1 = 1.555;
err_C1 = 0.08;
err_C0_2 = 0.4;
}
//Go to 2048 RAW
Chopper_openloop_set_block_ops(0,prime_or_redundant);
mois_tmcheck("Check that parameter HF_APR_CH_ROT is " + c0 + "V +/- " + err_C0 + "V. If not stop test and contact the HIFI ICC");
//Go to 2118 RAW
Chopper_openloop_set_block_ops(1,prime_or_redundant);
mois_tmcheck("Check that parameter HF_APR_CH_ROT has decreased by " + c1 + "V +/- " + err_C1 + "V with respect to its readout value at the previous step. If not stop test and contact the HIFI ICC");
//Back to 2048 RAW
Chopper_openloop_set_block_ops(0,prime_or_redundant);
mois_tmcheck("Check that parameter HF_APR_CH_ROT is " + c0 + "V +/- " + err_C0_2 + "V. If not stop test and contact the HIFI ICC");
//
StopMode_block_mois();
mois_spacon("Write down the OBS_ID corresponding to this mode and communicate it to the HIFI ICC");
}
//FSW hotcold, procedure
procedure Hot_cold_FSW_fm {
string band = "1a";
int integ_time = 8; //Total integration time for delay computation
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast
}{
Hot_spectra_FSW_fm(band,integ_time,backend);
Cold_spectra_FSW_fm(band,integ_time,backend);
}
// WBS stand-by, block
block WBS_standby_block_ops HIFI 7703 {
string band = "0"; // HIFI band
string laser_H = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-V laser to be set ON
}{
//Get default latchup level
{double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_latchup_s","hwv_latchup_s"],"0",0.0);
//
//Set zero ON
Hifi_HIFI_switch_zero_WBS_H($BBID,"ON");
Hifi_HIFI_switch_zero_WBS_V($BBID,"ON");
delay(1);
//Will be done at end of procedure during instrument mode status check
//mois_tmcheck("Check that parameter HWH_Zero_S is ON");
//mois_tmcheck("Check that parameter HWV_Zero_S is ON");
//Standby configuration
//H-Polarization
//
string hwh_laser1_s = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
int hwh_heater = 0;
//000
string hwh_latchup_s = result_d[0]{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"],band,0.0);
int wbs_config_delay = iround(result[0]{0});
//delay(wbs_config_delay); //Wait for configuration to be applied
//
//V-Polarization
//
string hwv_laser1_s = "OFF";
string hwv_laser2_s = "OFF";
if(laser_V == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_V == "Laser2") {
hwv_laser2_s = "ON";
}
int hwv_heater = 0;
//000
string hwv_latchup_s = result_d[1]{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
//
//Will be done at end of procedure during instrument mode status check
//mois_tmcheck("Check that parameter HWH_Laser1_S is " + hwh_laser1_s);
//mois_tmcheck("Check that parameter HWH_Laser2_S is " + hwh_laser2_s);
//mois_tmcheck("Check that parameter HWV_Laser1_S is " + hwv_laser1_s);
//mois_tmcheck("Check that parameter HWV_Laser2_S is " + hwv_laser2_s);
//mois_tmcheck("Check that parameter HWH_IN_ATT is set to 15, and parameters HWH_Band_1_ATT, HWH_Band_2_ATT, HWH_Band_3_ATT, HWH_Band_4_ATT are set to 7");
//mois_tmcheck("Check that parameter HWV_IN_ATT is set to 15, and parameters HWV_Band_1_ATT, HWV_Band_2_ATT, HWV_Band_3_ATT, HWV_Band_4_ATT are set to 7");
}
// 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;
}
// Take total power spectra, block
// Use AOT efficient timing
block Spectro_total_power_AOTLike_block_fm HIFI 3930 {
string band = "1a"; // HIFI band
int[] timing_parms = [4,1]; //single readout time in sec. and n_wbs_start
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
int integ_time = timing_parms[0] * timing_parms[1];
//Compute data-rate
double[] rates = ILT_datarate_proc_fm(band,backend,"tp",integ_time);
//Take spectrum
// set data rates
non_ess_hk_data_rate(rates[2] / 1024.0);
data_rate(rates[0] / 1024.0);
//
Hifi_HIFI_Spectr_total_power($BBID);
delay(integ_time);
//
// reset data rates
non_ess_hk_data_rate(rates[1] / 1024.0);
data_rate(0.0);
}
///////////////////////////////////////////////////////
// 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);
}
// Integrate only on internal hot, block
// We take 1 spectrum per phase.
block Stability_inthot_fm HIFI 3425 {
string band = "1a"; // HIFI band
int n = 100; //The number of integrations
int integ_time = 4; //Total integration time in sec. to be set at end of test
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code
string obsmode = "fastchop" in ["fastchop","tp"]; //tp or fastchop
double chop_phase = 1.0 in [0.2,2.0]; // Chop phase length
}{
Start_block();
Chopper_Rotation_proc_fm(band,"chop_M3_ang","chop_hot_ang");
//Look at HBB
//Get chopper settings
{double,string}[] result = ConfigurationReader("name_confilfpu",["chop_hot"],band,0.0);
double chop_hot = result[0]{0};
//Do a long integration:
// - for B1-5, use 2 sec. with wbs or hrs only, thus tp is OK
// - for B6: use 1 sec. with reduced wbs (wbsFast), thus tp is OK
//We implement a special spectroscopy configuration with fixed values
if(obsmode == "tp") {
Total_power_spectro_for_Stability_proc_fm(band,n,integ_time,backend,hrs_mode);
}
if(obsmode == "fastchop") {
Fast_chop_spectro_for_Stability_proc_fm(band,n,integ_time * 2,backend,hrs_mode,chop_hot,chop_hot,chop_phase);
}
}
//LCU IV curves, procedure
procedure Measure_LCU_IV_proc_fm {
string band = "1a" in ["ALL","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string multiplier = "M1" in ["ALL","M1","M2","M3"]; //Multiplier to be measured: M1, M2 or M3
int operation_delay = 60; //When ALL is selected, Waiting delay between two measurements on a band (e.g. to change connector)
}{
//
//Array of names
string[] band_array = ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"];
string[] multiplier_array = ["M1","M2","M3"];
//
//Case of all bands done
string band_loop = "1a";
string multiplier_loop = "M1";
//
if(band == "ALL") {
//loop on bands
for(int i = 1 .. 14) {
//Translate band name
band_loop = band_array[i - 1];
if(multiplier == "ALL") {
for(int j = 1 .. 3) {
multiplier_loop = multiplier_array[j - 1];
Measure_LCU_IV_block_fm(band_loop,multiplier_loop);
}
} else {
Measure_LCU_IV_block_fm(band_loop,multiplier);
}
delay(operation_delay);
}
} else {
//do only one band
if(multiplier == "ALL") {
for(int k = 1 .. 3) {
multiplier_loop = multiplier_array[k - 1];
Measure_LCU_IV_block_fm(band,multiplier_loop);
}
} else {
Measure_LCU_IV_block_fm(band,multiplier);
}
delay(operation_delay);
}
//
}
//HIFI LO tuning, block
//Target current is read from look-up table
block LO_tuning_block_fm HIFI 3616 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Start_block();
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//
//Get target mixer current
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_configlcu = "name_configlcu_a";
string name_configlo = "name_configlo_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_configlcu = "name_configlcu_b";
name_configlo = "name_configlo_b";
name_confindex = "name_confindex_b";
name_configlotune = "name_configlotune_b";
name_configlcutune = "name_configlcutune_b";
}
//
result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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 = result[0]{1};
string curlim2 = result[1]{1};
//
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};
//
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,lo_freq);
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 middle_d2 = result[0]{0};
double drain2_v_start = min(middle_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);
//
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
//Send command
HIFI_Configure_LCU_proc_fm(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);
//
//delay(5); //to settle at this value
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "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_nom_3b($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 == "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);
}
//
delay(1);
//
//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
HIFI_HL_store_tm_only_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//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
}{
//Anticipated implementation of SCR-2220
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[0]{0};
}
if(band == "2a") {
drain2_min = result[0]{0};
}
if(band == "2b") {
drain2_min = result[0]{0};
}
if(band == "3a") {
drain2_min = result[0]{0};
}
if(band == "3b") {
drain2_min = result[0]{0};
}
if(band == "4a") {
drain2_min = result[0]{0};
}
if(band == "4b") {
drain2_min = result[0]{0};
}
if(band == "5a") {
drain2_min = result[0]{0};
}
if(band == "5b") {
drain2_min = result[0]{0};
}
if(band == "6a") {
drain2_min = result[0]{0};
}
if(band == "6b") {
drain2_min = result[0]{0};
}
if(band == "7a") {
drain2_min = result[0]{0};
}
if(band == "7b") {
drain2_min = result[0]{0};
}
return drain2_min;
}
////////////////////////////////////
// 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;
}
//General script to reset the LCU, block
block LCU_Reset_block_mois HIFI 7566 {
}{
//
Hifi_HIFI_HL_Reset($BBID);
mois_spacon("Check that LCU HK is coming in, e.g. in AND LCU_Status2. Check that HL_MODE_S is set to standby1");
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// The blocks
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Integration on Internal cold, block
block Cold_spectra_fm HIFI 3222 {
string band = "1a";
int integ_time = 4; //Total integration time in sec.: at least 2sec !
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//Rotate chopper: assume we come from M3
Chopper_Rotation_proc_fm(band,"chop_M3_ang","chop_cold_ang");
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
}
////////////////////////////////////
// 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;
}
//Set DC bias without switching on the chain, block
//All input parameters shall be given by the user
block LCU_DC_health_check_block_fm HIFI 3699 {
string band = "1a" in ["ALL","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double plevel_v = 0.0; // HL_PL_C
double m1_v = 0.0; // HL_M1_V
double m2_v = 0.0; // HL_M2_V
double m3_v = 0.0; // HL_M3_V
double gate1_v = 0.0; // HL_Gate1_V
double gate2_v = 0.0; // HL_Gate2_V
double drain1_v = 0.0; // HL_Drain1_V
string curlim1_v = "1.5" in ["1.5","1.3","1.22","1.4"]; // HL_Curlim1
double drain2_v = 0.0; // HL_Drain2_1A_V
string curlim2_v = "1.5" in ["1.5","1.3","1.22","1.4"]; // HL_Curlim2
}{
//
//Start_block();
//
//Execute configuration
//Check which LO band is used
if(band == "1a") {
//Band 1a
Hifi_HIFI_Conf_diag_LCU_ch1a($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "1b") {
//Band 1b
Hifi_HIFI_Conf_diag_LCU_ch1b($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "2a") {
//Band 2a
Hifi_HIFI_Conf_diag_LCU_ch2a($BBID,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "2b") {
//Band 2b
Hifi_HIFI_Conf_diag_LCU_ch2b($BBID,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "3a") {
//Band 3a
Hifi_HIFI_Conf_diag_LCU_ch3a($BBID,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "3b") {
//Band 3b
Hifi_HIFI_Conf_diag_LCU_ch3b($BBID,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "4a") {
//Band 4a
Hifi_HIFI_Conf_diag_LCU_ch4a($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "4b") {
//Band 4b
Hifi_HIFI_Conf_diag_LCU_ch4b($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "5a") {
//Band 5a
Hifi_HIFI_Conf_diag_LCU_ch5a($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "5b") {
//Band 5b
Hifi_HIFI_Conf_diag_LCU_ch5b($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "6a") {
//Band 6a
Hifi_HIFI_Conf_diag_LCU_ch6a($BBID,plevel_v,m1_v,m2_v,m3_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "6b") {
//Band 6b
Hifi_HIFI_Conf_diag_LCU_ch6b($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "7a") {
//Band 7a
Hifi_HIFI_Conf_diag_LCU_ch7a($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
if(band == "7b") {
//Band 7b
Hifi_HIFI_Conf_diag_LCU_ch7b($BBID,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1_v,drain2_v,curlim2_v);
}
//
//Then need to switch on band
string band_new = Translate_band_name(band);
Hifi_HIFI_HL_switchon($BBID,"channel_" + band_new);
//
{double,string}[] result = ConfigurationReader("name_delays",["switch_on_delay"],"0",0.0);
int switch_on_delay = iround(result[0]{0});
delay(switch_on_delay);
//
//Switch off band to prepare for next band
Hifi_HIFI_HL_Switch_off($BBID);
//
result = ConfigurationReader("name_delays",["switch_off_delay"],"0",0.0);
int switch_off_delay = iround(result[0]{0});
delay(switch_off_delay);
}
// 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);
}
// Switch HIFI to primary mode, mode
// This only switches the LO to normal mode
mode HifiManCmdSetIntoPrimary {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string laser_H = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-V laser to be set ON
string chopper_loop = "OPEN" in ["OPEN","CLOSE"]; //chopper loop status
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
Mode_status_check_standby_II(laser_H,laser_V,chopper_loop,"up",prime_or_redundant);
mois_comment("Set HIFI to Primary mode with " + laser_H + " switched on");
//
StartMode_block_ops();
//Switch LO to nominal
mois_step("Set LOU to normal mode");
Set_LO_Nominal_block_ops();
//
StopMode_block_mois();
Mode_status_check_primary(laser_H,laser_V,chopper_loop);
}
// 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;
string modeName = "freq" in ["freq","fs-freq","load-freq"]; // reference scheme to use
}{
// 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;
// translate modeName names ["freq",fs-freq",load-freq"] into
// refmode names ["dbs","fs","lchop"]
if(modeName == "fs-freq") {
string refmode = "fs";
} else {
if(modeName == "load-freq") {
refmode = "lchop";
} else {
refmode = "dbs";
}
}
// Call CUS routine
int grouplen = GetSpectralScanGroupLength(band,lo_freq,lo_freq_up,redundancy,refmode);
return grouplen;
}
//Set LOU to diagnostic, block
block Set_LO_Diagnostic_block_fm HIFI 3664 {
}{
//
//Start_block();
{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_Diagnostic($BBID);
delay(set_to_nominal_delay);
//
}
// Recalculate and verify LCU memory checksum at end of obsid or OD
block LcuChecksumRecalcCloseObs_aot HIFI 7906 {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
bool alltables = true; //check all tables+unused (true), or only one band table (false)
}{
if(alltables) {
//Check all tables
string block_IF_NOK = "NO";
LcuChecksumRecalcSegmented_aot(band,"Table_all",block_IF_NOK);
//Check un-used area
block_IF_NOK = "NO";
LcuChecksumRecalcSegmented_aot(band,"Unused",block_IF_NOK);
//ICU all memory checks - HIFI-3662 - commented out for the moment
OBS_SEU_check_aot("ALL");
} else {
//Check table only
block_IF_NOK = "NO";
LcuChecksumRecalcSegmented_aot(band,"Table",block_IF_NOK);
}
}
//////////////////////////////////////////////
/// Blocks
//////////////////////////////////////////////
//General LO configuration command
// Uses SFT approach with old 5 TM TC call
block HIFI_Configure_LCU_block_sft HIFI 3977 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //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);
//
//Start_block();
//
//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);
//
//Store settings into available register
//HIFI_HL_store_tm_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_OLD_proc_fm();
}
// Functional test with unpumped mixer, procedure
// This case assumes no backend attenuator setting is done
procedure FT_unpumped {
string band = "1a"; // HIFI band
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3,wb4,etc
int integ_time = 4; //Integration time
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Do not switch-off LO, rather, use the dissipative mode
//LCU_switch_off_block_fm();
LCU_config_dissipative_w_D2_proc_aot(band);
//Fix for SPR-2520: init mixer band
double[] result_d = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = result_d[0];
Init_MSA_HBB_fm(band,"CLOSE",lo_freq,"ON");
//
//WBS calibration
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
}
//
//(Re)configure spectrometers integration
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
//Measure IF noise
IFcalibration(band,integ_time,backend);
//IVcurve before and after magnet set to 0: not for band 6
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
//IV curve with default parameters
IVcurve_raw_fm(band);
//Set magnet to zero and get IVcurve: only up to band 5 since band6-7 have no magnets
IVcurve_with_zero_magnet_fm(band);
//Heater
Heater_fm(band);
//Now sets back the magnet to nominal value
//Set magnet to zero and get IVcurve: only up to band 5 since band6-7 have no magnets
IVcurve_with_zero_magnet_fm(band);
}
//IVcurve after defluxing
IVcurve_defluxed_fm(band);
}
//HIFI-COP-2.3-Param-Scan: 1 per pair of scanned parameters
obs HifiEng_Parameter_Scan_COP {
int index = 1 in [1,7]; // Test case index as of config_paramscan_COP.config
int phase = 1 in [1,2]; //Measurement phase
int m1_index = 1 in [1,5]; //Index of M1 value - only applicable is phase = 1. Index 1 is least negative
int m2_index = 1 in [1,5]; //Index of M2 value - only applicable is phase = 1. Index 1 is least negative
int bias_index = 1 in [1,3]; //Index of bias value - only applicable is phase = 2
int imix_index = 1 in [1,3]; //Index of Imix value - only applicable is phase = 2
}{
//Read corresponding band
string tab = "config_paramscan_COP.config";
string band = slookup(tab,"" + index,"band");
//General parameters in use
int integ_time = 4;
//Integration time PER PHASE for the slowchop measurement
string[] hrs_mode = ["wb1","wb1"];
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Parameter_Scan_COP_proc_ops(index,phase,integ_time,hrs_mode,m1_index,m2_index,bias_index,imix_index));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Parameter_Scan_COP_proc_ops(index,phase,integ_time,hrs_mode,m1_index,m2_index,bias_index,imix_index);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
// Step 1 of QLA_Testcontrol fine magnet-tuning loop
// Minimum IF power in the spectra
block Magnet_scan_fine_fm HIFI 3203 {
string band = "1a";
int integ_time = 4; //Integration time
double lo_freq = 522.0; //LO frequency
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
Start_block();
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["magnet_current_min_h","magnet_current_max_h","magnet_current_min_v","magnet_current_max_v","jitter_margin","magnet_steps_h","magnet_steps_v"],band,0.0);
//H polar
double magnet_min_h = result_d[0]{0};
double magnet_max_h = result_d[1]{0};
//V polar
double magnet_min_v = result_d[2]{0};
double magnet_max_v = result_d[3]{0};
//
double magnet_min = max(magnet_min_h,magnet_min_h);
double magnet_max = min(magnet_max_h,magnet_max_h);
//
int jitter_margin = iround(result_d[4]{0});
int duration_scan = 0;
double step_duration = double(2 + 2 * jitter_margin);
int max_per_command = 40;
int steps = 0;
int steps_done = 0;
//
int steps_wanted_h = iround(result_d[5]{0});
int steps_wanted_v = iround(result_d[6]{0});
int steps_wanted = iround(max(double(steps_wanted_h),double(steps_wanted_v)));
//
double step = Stepsize(magnet_min,magnet_max,steps_wanted,"hifi_HIF_mx_mg_step_C");
double margin = Stepmargin(magnet_min,magnet_max,"hifi_HIF_mx_mg_step_C");
steps_wanted = 1 + iceil((magnet_max - magnet_min) / step);
// force the last portion to less than max_per_command
if(max_per_command * (steps_wanted / max_per_command) == steps_wanted) {
steps_wanted = steps_wanted - 1;
}
//
//Set magnet to maximum to avoid hysteresis
Hifi_HIFI_CH1_MX_MG_C($BBID,magnet_max_h);
Hifi_HIFI_CV1_MX_MG_C($BBID,magnet_max_v);
delay(1);
//
double magnet_current_h = magnet_min_h;
double magnet_current_v = magnet_min_v;
//
//We use special biasing to evidence the minima in the magnet scan
result_d = ConfigurationReader("name_confilmix",["bias4magn_h","bias4magn_v"],band,lo_freq);
double bias_h = result_d[0]{0};
double bias_v = result_d[1]{0};
//
//Start scan: from max. to min. magnet downward.
while(steps_done < steps_wanted) {
steps = steps_wanted - steps_done;
if(steps > max_per_command) {
steps = max_per_command;
}
magnet_current_h = magnet_max_h - double(steps_done) * step;
magnet_current_v = magnet_max_v - double(steps_done) * step;
Hifi_HIFI_CH1_MX_MG_C($BBID,magnet_current_h);
Hifi_HIFI_CV1_MX_MG_C($BBID,magnet_current_v);
delay(1);
HIFI_Spectr_total_power_proc_fm(band,backend,integ_time);
//
steps_done = steps_done + 1;
}
//Back to nominal values
//First set magnet to maximum to avoid hysteresis
Hifi_HIFI_CH1_MX_MG_C($BBID,magnet_max_h);
Hifi_HIFI_CV1_MX_MG_C($BBID,magnet_max_v);
delay(1);
//Nominal values
result_d = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v","norm_bias_h","norm_bias_v"],band,lo_freq);
magnet_current_h = result_d[0]{0};
magnet_current_v = result_d[1]{0};
bias_h = result_d[2]{0};
bias_v = result_d[3]{0};
Hifi_HIFI_FCU_parameter_scan($BBID,1,1,step_duration,bias_h,bias_v,0.0,magnet_current_h,magnet_current_v,0.0);
delay(2);
}
// Sort array, bubblesort, maximum will be first element
double[] procedure DSort {
double[] x = [0.0]; // Input array
int nlen = 1; // Array length (keep dan gling numbers untouched)
}{
double tmpstore = 0.0;
// double loop
for(int i = 0 .. nlen - 2) {
for(int j = 1 .. nlen - 1 - i) {
if(x[j] > x[j - 1]) {
tmpstore = x[j];
x[j] = x[j - 1];
x[j - 1] = tmpstore;
}
}
}
return x;
}
/////////////////////////////////////////////////////////////////
// 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}};
}
// Compute Slow Chop delay necessary for integration, procedure
procedure Apply_Slow_Chop_delay {
int total_time = 12; //single readout time * n_wbs_start
string band = "1a"; // HIFI band
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Packet transfer time
{double,string}[] result = ConfigurationReader("name_delays",["wbs_transfer_delay"],band,0.0);
//
int wbs_packet_transfer_time = iround(result[0]{0});
//
//In case less channels are used, one must adapt the transfer time
if(backend == "hrs" || backend == "wbs") {
//wbs_packet_transfer_time = 0; //3000;
}
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
//expect half backend
//wbs_packet_transfer_time = 0; //2000;
}
//
//Compute delay
int delay_slow_chop = total_time + wbs_packet_transfer_time / 1000;
//debug_print("Slow Chop delay: " + delay_slow_chop + " sec");
//
//Apply delay
delay(delay_slow_chop);
//
}
//////////////////////////////////////////////////////////////////////
// Compatibility procedure to provide the same API as used in
// the previous versions
//
// Returns the actual integration time and the dead time per phase
{double,double} procedure ConfigSpectroscopySlowChop {
/* 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 = "1a"; // HIFI band
double lo_freq = 522000.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}
bool docommands = false; // Whether instrument command is issued
}{
// 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};
int tdead = timing{8};
int tint_act = timing{9};
// 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
if(docommands) {
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 actual integration time and dead time per readout
return {double(tint_act) / 1000.0,double(tdead) / 1000.0};
}
//HIFI-COP-2.1-CPR-RespTime
procedure Chopper_Response_time_COP_proc_ops {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_comment("This test needs the successful execution and analysis of the full chopper health check suite");
mois_comment("Start of HIFI Chopper response time test");
mois_comment("Please check that instrument was switched on with the " + prime_or_redundant + " unit");
//General parameters in use
string band = "1a";
// HIFI band
double lo_freq = 520.0;
//LO frequency
string hbb_heater = "ON";
//hot source on/off
string chopper_loop = "CLOSE";
int milliSecSample = 3;
// interval between samples
int samplesBefore = 30;
int samplesAfter = 1000;
//
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
if(chopper_loop == "OPEN") {
result = ConfigurationReader("name_chopper",["chop_startup_warm"],"0",0.0);
}
//
mois_step("Init FPU");
Init_MSA_ops(band,chopper_loop,lo_freq,result[0]{0},hbb_heater,prime_or_redundant);
mois_step("Rotate to hot internal load");
//Rotate to HBB
Chopper_Rotation_block_fm_COP(band,"chop_M3right_ang","chop_hot_ang",prime_or_redundant);
mois_step("Response time sequence");
//Chopper response time
Chopper_Response_time_block_COP(band,milliSecSample,samplesBefore,samplesAfter,prime_or_redundant);
//
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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,"dbs",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};
}
// 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;
}
/////////////////////////////////////////////////////////////////
// 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 Engineering - Jupiter - DBS slowChop",{data_time,0,0,n_switch_on,0,0,0,0,n_cycles,load_interval});
ChopMessages(false,data_time,n_switch_on);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
//Set LOU to nominal, block
//no channel selected
block Set_LO_Nominal_block_ops HIFI 7626 {
}{
//
{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);
//Will be done at end of procedure during instrument mode status check
//mois_tmcheck("Check that parameter HL_MODE_S is normal");
//
}
// 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);
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
// LCU switch-off, block
block LCU_switch_off_block_ops HIFI 7631 {
}{
//
{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);
//Will be done at end of procedure during instrument mode status check
//mois_tmcheck("Check that parameter HL_Channel_S is Off");
delay(switch_off_delay);
//
//Set heater to their stby value: should not depend on band
HL_heater_proc_ops("1a","stby");
}
//General script to clear error flags and set to nominal, block
block LCU_disable_all_bands_block_fm HIFI 3767 {
}{
//
//switch to standby
{double,string}[] result = ConfigurationReader("name_delays",["stdby_delay"],"0",0.0);
int stdby_delay = iround(result[0]{0});
mois_comment("Set LOU to standby");
Hifi_HIFI_HL_Standby($BBID);
delay(stdby_delay);
//Disable bands
mois_comment("Disable all bands");
mois_spacon("In the next TC, parameter HP443194 should be treated as FP");
Hifi_HIFI_Conf_LCU_internal($BBID,0,"RESET","RESET",256);
//sets bandmask to 3FFF: all bands
//LSU_delta_f: 256 = 88mV
//
}
//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 (" + drain2_v + " V), was commanded above its blue max (" + drain2_max + " V).");
}
//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 (" + drain2_v + " V), was commanded below its blue min (" + drain2_min + " V).");
}
return drain2_v_new;
}
//TM to control FDIR on Standby0 watchdog
block Enable_Standby0_FDIR_block_mois HIFI 3854 {
}{
// BBID needs to be set manually as the main TC command has no BBID argument
Hifi_HIFI_Set_OBS_ID($BBID,$OBSID);
delay(1);
//
int n_breach = 1;
Hifi_HIFI_LCUmode_check_on(n_breach);
delay(1);
//
}
// Step 2 of QLA_Testcontrol coarse magnet-tuning loop
block Magnet_set_coarse_with_IVcurve_fm HIFI 3202 {
string band = "1a";
}{
Start_block();
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["bias_min_h","bias_max_h","bias_steps_h","bias_min_v","bias_max_v","bias_steps_v"],band,0.0);
//H polar
double bias_min_h = result_d[0]{0};
double bias_max_h = result_d[1]{0};
int steps_h = iround(result_d[2]{0});
//V polar
double bias_min_v = result_d[3]{0};
double bias_max_v = result_d[4]{0};
int steps_v = iround(result_d[5]{0});
//Bias to set at end of IVC
//Need a representative frequency: take keyfreq
double[] result = CalibrationReader("name_keyfreq",["keyfreq"],band,0.0);
double lo_freq = result[0];
//
result_d = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v","norm_magn_h","norm_magn_v"],band,lo_freq);
double bias_h = result_d[0]{0};
double bias_v = result_d[1]{0};
//Fetch magnets only if band is not band6
double magnetcurrent_h = 0.0;
double magnetcurrent_v = 0.0;
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
magnetcurrent_h = result_d[2]{0};
magnetcurrent_v = result_d[3]{0};
}
//
//The IVCurve is done on the smallest range and the finest step
double bias_min = max(bias_min_h,bias_min_v);
double bias_max = min(bias_max_h,bias_max_v);
int steps = iround(max(double(steps_h),double(steps_v)));
//
//Set magnet to maximum to avoid hysteresis
result_d = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,0.0);
double magnet_current_max_h = result_d[0]{0};
double magnet_current_max_v = result_d[1]{0};
Hifi_HIFI_CH1_MX_MG_C($BBID,magnet_current_max_h);
Hifi_HIFI_CV1_MX_MG_C($BBID,magnet_current_max_v);
delay(1);
//Do IV curve
IVcurve(band,bias_min,bias_max,steps,magnetcurrent_h,magnetcurrent_v,bias_h,bias_v);
}
////////////////////////////////////////
// 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};
}
/////////////////////////////////////////////////////////////////
// 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,imin(data_time,data_time_off));
{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,"lchop");
int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0);
// 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,reffreq,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 = 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;
}
// 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;
}
// Additional constraint of compatibility of group size with load period
int loadperiod = LoadPeriod(band,reffreq,effResolution{1});
// 80% margin
int periodlimit = loadperiod * 4 / 5;
// elements of cycle - compute cycle duration
int tunedelay = LOSettlingTime(band,reffreq / 1000.0,false,true);
int load_datatime = imax(data_time_guess,data_time_off_guess);
int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,effResolution{0},load_datatime,backendreadoutparms));
int perfreqtime = 2 * (data_time_guess * n_switch_on_guess + data_time_off_guess * n_switch_off_guess + tunedelay);
int cycle = perfreqtime * n_freq_point_guess + loadlength;
if(cycle > periodlimit) {
n_freq_point_guess = imax((periodlimit - loadlength) / perfreqtime,1);
}
int n_freq_point_range = 1 - n_freq_point_guess;
if(n_freq_point_range == 0) {
n_freq_point_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;
}
//OBS autonomous function against LCU checksum corruption - SCR-3069
mode HifiManCmd_CRC_FDIR_enable {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to enable LCU checksum verification");
StartMode_block_ops();
//
mois_spacon("Verify that HM123190 (HI_au_LCU_mem_S) is OFF. If it is ON check with ICC whether this is fine to proceed");
mois_step("Enable LCU checksum verification");
Enable_CRC_FDIR_block_mois();
//
mois_spacon("Verify that HM123190 (HI_au_LCU_mem_S) is ON");
StopMode_block_mois();
}
/////////////////////////////////////////////////////////////////////////
// Auxiliary routine to check the actual duration of telescope lines
//
{int,int} procedure OtfTelescopeLine {
int line_inttime = 10; // actual integration time in OTF line
int line_telescope = 11; // duration of an OTF line from spacecraft
}{
// Initialize
int line_time = line_inttime;
int line_start = 0;
// The telescope slew can be a bit further than requested
if(line_telescope < line_inttime) {
CError("OTF scan length returned by telescope too short for instrument.");
}
if(line_telescope > line_inttime) {
line_time = line_telescope;
line_start = (line_telescope - line_inttime) / 2;
}
return {line_time,line_start};
}
//HIFI LO tuning and vector scan, block
block LO_tuning_Vecscan_M1M2_block_fm HIFI 3792 {
string band = "7b" in ["7b","7bb"]; // HIFI band
double lo_freq = 1890.0; //LO frequency
double m1v = -7.6; //M1V
double m2v = -12.0; //M2V
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
//Prepare for tuning
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//
//Get target mixer current
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});
}
//
//Start_block();
//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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],band,lo_freq);
double plevel_v = result[0]{0};
double m1_v = m1v;
//result[1]{0};
double m2_v = m2v;
//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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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});
//
cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lo_freq);
double drain2_safe = cresult[0];
drain2_v_start = drain2_safe;
//For this test, we will only go as low as best-guess minus 20%
result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq);
double drain2_bestguess = result[0]{0};
drain2_v_start = drain2_bestguess * 0.8;
//
double drain2_max = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq);
//
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;
//
//For bands 1 to 5, scan will be done with increasing drain2 voltages
//
//For bands 6 to 7, scan will be done with decreasing drain2 voltages: NOT FOR THIS TEST !!
if(band == "6a" || band == "7a" || band == "6b" || band == "7b") {
//step_drain2_v = -1.0*step_drain2_v;
//drain2_v_start = drain2_max;
//Also, it probably makes no sense to go down to the safe value
drain2_v_start = drain2_safe + 0.45;
//i.e. go to 1.7
//Need to check that drain2_v_start has not got above the blue max
//If so, the range to scan is not so big so we stick to the safe value
//as minimum drain2 for the scan
if(drain2_v_start >= drain2_max) {
drain2_v_start = drain2_safe;
}
}
//
result = ConfigurationReader(name_configlotune,["nsteps","step_time"],band,lo_freq);
int nsteps = iround(result[0]{0});
double step_drain2_v = -1.0 * (drain2_max - drain2_v_start) / double(nsteps - 1);
drain2_v_start = drain2_max;
//We use a shorter step time here: 1s instead of 5s
double step_time = 1.0;
//result[1]{0};
//
//Preliminary configuration at high Vd2
//
//Compute config_lo_delay: new approach: use ramp-up time
result = ConfigurationReader("name_delays",["lock_lo_delay","vd2_rampup_speed"],band,lo_freq);
int config_lo_delay = iceil(result[0]{0} + (drain2_v_start - drain2_safe) / result[1]{0});
//Old approach: fixed delay
//result = ConfigurationReader("name_delays",
// ["config_lo_delay"],band, lo_freq);
//int config_lo_delay = iround(result[0]{0});
//
//Send command
if(band == "1a") {
if(lo_freq < 535.5) {
error("At that frequency you cannot control M1V");
//Hifi_HIFI_Conf_safe_LCU_ch1a($BBID,freq_nx,lsu_main,lsu_offset,
// d2_step,drain2_v_start,curlim2,macro_checksum);
} else {
Hifi_HIFI_Conf_nom_LCU_ch1a($BBID,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,macro_checksum);
}
}
if(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,drain2_v_start,curlim2,macro_checksum);
}
if(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,drain2_v_start,curlim2,macro_checksum);
}
if(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,drain2_v_start,curlim2,macro_checksum);
}
//Command delay
delay(config_lo_delay);
//
//Load vector scan
//Check which LO band is used
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
error("At that frequency you cannot control M1V");
//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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "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 == "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);
}
//
//delay(1);
//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
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//General script to clear error flags and set to nominal, block
block LCU_disable_FreqTMY_check_block_fm HIFI 3667 {
}{
//
//Start_block();
//switch to standby
Hifi_HIFI_HL_Standby($BBID);
{double,string}[] result = ConfigurationReader("name_delays",["stdby_delay"],"0",0.0);
int stdby_delay = iround(result[0]{0});
delay(stdby_delay);
//Clear error flags
Hifi_HIFI_Conf_LCU_internal($BBID,16383,"SET","RESET",256);
//sets bandmask to 3FFF: all bands
//LSU_delta_f: sets to 256 = 88mV
//Switch back to nominal
Hifi_HIFI_HL_Normal($BBID);
int set_to_nominal_delay = stdby_delay;
delay(set_to_nominal_delay);
//
}
// WBS configuration with minimum attenuation, block
// Laser setup as in config file
block WBS_config_min_att_block_fm HIFI 3639 {
string band = "1a"; // HIFI band
}{
//Start_block();
//H-Polarization
//
{double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s"],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 = 0;
int hwh_att_band3 = 0;
int hwh_att_band2 = 0;
int hwh_att_band1 = 0;
int hwh_att_in = 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);
//V-Polarization
//Get configuration parameters
//
result_d = ConfigurationReader("name_configwbs",["hwv_laser1_s","hwv_laser2_s","hwv_heater","hwv_latchup_s"],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 = 0;
int hwv_att_band3 = 0;
int hwv_att_band2 = 0;
int hwv_att_band1 = 0;
int hwv_att_in = 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);
//
//Wait delay to allow all setting to be configured
delay(wbs_config_delay);
}
// 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};
}
// Single zero measurement
block WBS_Zero_block HIFI 6015 {
}{
// dummy parameters for configuration reader
string band = "4a";
// HIFI band
double lo_freq = 978200.0;
// LO frequency
// Get delays
{double,string}[] result = ConfigurationReader("name_delays",["wbs_zero_delay"],band,lo_freq);
int wbs_zero_delay = iround(result[0]{0});
int data_time = wbs_zero_delay;
// 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 = AllDataRates(fullreadoutparms,data_time,false);
int readout = fdataparms{0};
// set data rates
non_ess_hk_data_rate(fdataparms{1}[2] / 1024.0);
data_rate(fdataparms{1}[0] / 1024.0);
// Call commands
Hifi_HIFI_WBS_Zero($BBID);
delay(wbs_zero_delay);
// reset data rates
non_ess_hk_data_rate(fdataparms{1}[1] / 1024.0);
data_rate(0.0);
// additional delay for packet transmission
// Not needed if followed by commands without science packets
// delay(readout);
}
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;
}
//!!!!!!!!!!!!!!!!!!!!
// Associated blocks
//!!!!!!!!!!!!!!!!!!!!
// Procedure to compute the parameters needed in a Chopped HRS fast measurement
block Stability_chopped_fasthrs_block HIFI 3439 {
/* Integration time */
string band = "1a"; // HIFI band
double lo_freq = 522.0; // LO frequency
int data_time = 10; // Chop phase length
int n_data = 10; // Number of phases
double hrs_readout = 0.333; // HRS readout length
}{
// Fixed backend configuration
// No WBS
int wbsh_offset1 = 0;
int wbsh_width1 = 0;
int wbsh_offset2 = 2048;
int wbsh_width2 = 0;
int wbsh_offset3 = 4096;
int wbsh_width3 = 0;
int wbsh_offset4 = 6144;
int wbsh_width4 = 0;
int wbsv_offset1 = 0;
int wbsv_width1 = 0;
int wbsv_offset2 = 2048;
int wbsv_width2 = 0;
int wbsv_offset3 = 4096;
int wbsv_width3 = 0;
int wbsv_offset4 = 6144;
int wbsv_width4 = 0;
string packing = "24_bits_format";
// HRS
int hrsh_sel = 128;
//10000000 = 1U only
int hrsv_sel = 128;
//10000000 = 1U only
// No bitshift
int hrs_rshift = 0;
int wbs_rshift = 0;
// Timing - copied from ConfigSpectroscopyParams
// 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 given by switch dead time
double res = GetLoadChopDeadTime(band,lo_freq);
// minimum delay
int 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","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[7]{0});
int wbs_chunksize = iround(result[4]{0});
int tacc_add = iround(result[5]{0});
int min_wbs_acc = iround(result[6]{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
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;
// No WBS addition in ICU
int n_wbs_integr = 1;
int n_wbs_start = n_data;
// HRS
int hrs_phase = iceil(1000.0 * hrs_readout);
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 = 1;
// Issue configuration
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_offset1,wbsh_width1,wbsh_offset2,wbsh_width2,wbsh_offset3,wbsh_width3,wbsh_offset4,wbsh_width4,wbsv_offset1,wbsv_width1,wbsv_offset2,wbsv_width2,wbsv_offset3,wbsv_width3,wbsv_offset4,wbsv_width4,hrs_rshift,wbs_rshift,hrsh_sel,hrsv_sel,packing);
//
// Now call the spectroscopy
//Get appropriate chopper voltages
{bool,double,double} chopparms = GetChopVoltages(band,lo_freq,"chop_hot","chop_cold");
bool isPrime = chopparms{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(n_data * data_time + 3);
}
// 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};
}
//TM to control FDIR on LOU temp
block Set_LO_FDIR_temperatures_block_mois HIFI 3853 {
}{
// BBID needs to be set manually as the main TC command has no BBID argument
Hifi_HIFI_Set_OBS_ID($BBID,$OBSID);
delay(1);
//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
//
mois_spacon("In the next TC, the parameters HP460197 and HP461197 should be treated as FP");
Hifi_HIFI_LOU_T_check_on(nbreach,tmax,tmin);
delay(1);
//
}
// 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);
}
//HIFI measurement of HEB spectra variation vs Imix, procedure
//Takes spectra over the full Vd2 range
procedure Vector_scan_BLUE_LIMIT_w_spectra_proc_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //LO frequency
int intermediatetime = 900; //total time remaining to scan
}{
//Configure Spectro in total power
int[] res = [0,0];
string[] hrs_mode = ["wb1","wb1"];
int total_time = 4;
string backend = "both";
res = Configure_Spectrometer_proc_fm(band,total_time,hrs_mode,backend);
//
//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";
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";
}
//
{double,string}[] result = ConfigurationReader(name_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{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});
//
cresult = CalibrationReader("name_lcu_safe_values",["d2_v"],band,lo_freq);
double drain2_safe = cresult[0];
drain2_v_start = drain2_safe;
//Take lowest value from config_HEB_Imix_spec.config
string tabimix = "config_HEB_Imix_spec.config";
double bandnb = GetBandCode(band);
drain2_v_start = dlookup(tabimix,"" + iceil(bandnb),"vd2min");
drain2_v_start = Check_BLUE_LIMIT_D2_proc_fm(band,lo_freq,drain2_v_start);
//
double drain2_max = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq);
//Take highest value from config_HEB_Imix_spec.config
drain2_max = dlookup(tabimix,"" + iceil(bandnb),"vd2max");
//Clip to blue max
drain2_max = Check_BLUE_LIMIT_D2_proc_fm(band,lo_freq,drain2_max);
//
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;
//
//First step at max Vd2
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lodelay = iround(result[0]{0});
int config_lo_delay = config_lodelay;
//
int starttime = time();
//First setting at max Vd2
double drain2_v_current = drain2_max;
HIFI_Configure_LCU_proc_fm(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_current,curlim2,macro_checksum,config_lo_delay);
//
//Take spectrum
Spectro_total_power_block_fm(band,res,backend);
int iterationtime = time() - starttime - 2;
//remove 2 as further configlodelay are 2sec shorter
//Clear flag in case we have entered failure mode in the first setting
Set_LO_Nominal_proc_fm();
//From now on it's alea jacta est
//Scan is performed from top to bottom
//We compute the nb of step based on the time needed for one iteration
int nbstep = intermediatetime / iterationtime;
//Compute step size
double step_drain2_v = -1.0 * (drain2_max - drain2_v_start) / double(nbstep - 1);
//
//debug_print(nbstep);
//debug_print(step_drain2_v);
//Increment step
drain2_v_current = drain2_v_current + step_drain2_v;
//If not the first setting, the configuration time should be smaller
//as we don't change the frequency
config_lo_delay = config_lodelay - 2;
//Start loop on further settings
for(int i = 1 .. nbstep - 1) {
// while (drain2_v_current >= drain2_v_start) {
//Configure Vd2
HIFI_Configure_LCU_proc_fm(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_current,curlim2,macro_checksum,config_lo_delay);
//
//Take spectrum
Spectro_total_power_block_fm(band,res,backend);
//Increment step
drain2_v_current = drain2_v_current + step_drain2_v;
if(drain2_v_current < drain2_v_start) {
drain2_v_current = drain2_v_start;
}
}
}
//////////////////////////////////////////////////////////////////////
// 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}};
}
// Switch HIFI on, block
//
block HIFI_global_switch_on_block_ops HIFI 7925 {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
StartBlock_ops();
//Sequentially switches on, then notify PDU
//
//WBS-H
mois_step("Switch ON WBS-H S/S");
PDU_switch_on_proc_ops("WBS_H");
mois_comment("Notify PDU status for WBS-H");
HIFI_notify_PDU_status_on_proc_ops("ON","OFF","OFF","ON","OFF","OFF","WBSH");
//WBS-V
mois_step("Switch ON WBS-V S/S");
PDU_switch_on_proc_ops("WBS_V");
mois_comment("Notify PDU status for WBS-H");
HIFI_notify_PDU_status_on_proc_ops("ON","OFF","ON","ON","OFF","OFF","WBSV");
//HRS-H and HRS-V are first powered ON, FT#0 is done, then notify PDU
mois_step("Switch ON HRS-H S/S");
PDU_switch_on_proc_ops("HRS_H");
mois_step("Switch ON HRS-V S/S");
PDU_switch_on_proc_ops("HRS_V");
//HRS FT#0 and special HK handling for this
mois_step("HRS start-up");
mois_comment("House-keeping for HRS-H and HRS-V is de-selected");
Switch_HK_proc_ops("ON","ON","ON","ON","OFF","OFF");
mois_comment("Notify PDU status for HRS-H and HRS-V");
HIFI_notify_PDU_status_on_proc_ops("ON","OFF","ON","ON","OFF","ON","HRSH");
HIFI_notify_PDU_status_on_proc_ops("ON","OFF","ON","ON","ON","ON","HRSV");
HRS_functional_test_No_0_proc_ops();
mois_comment("House-keeping for HRS-H and HRS-V is selected again");
Switch_HK_proc_ops("ON","ON","ON","ON","ON","ON");
mois_comment("Initial configuration of HRS blocks and LO");
HRS_standby_proc_ops("0",["wb","wb"]);
//LOU
mois_step("Switch ON LO S/S");
string lo_subsys = "LO_Prime";
if(prime_or_redundant == "Red") {
lo_subsys = "LO_Red";
}
PDU_switch_on_proc_ops(lo_subsys);
mois_comment("Notify PDU status for LCU");
HIFI_notify_PDU_status_on_proc_ops("ON","ON","ON","ON","ON","ON","LCU");
}
//Deactivate checksum verification in MTL
obs HifiEng_CRC_FDIR_disable_MTL {
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Disable_CRC_FDIR_block_mois());
// 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) {
// Test execution
Disable_CRC_FDIR_block_mois();
}
if(state[0] == 5) {
//HIFISetHK("normal",true); // -> superfluous
HIFICloseObs();
}
}
}
{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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
//HIFI-COP-2.1-Stab-IF - goes into dissipative mode
obs HifiEng_stability_IF_system_COP {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//General parameters in use
int n = 751;
//Number of load pairs to be measured
string mixer_polarization = "B";
//Polarization: H, V, or both (B)
int integ_time = 4;
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//Use high biases
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_high_resistive_h"],band,0.0);
//
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"start");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Proc_stability_IF_system(band,n,hrs_mode,mixer_polarization,integ_time,backend,result[0]{0}));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Proc_stability_IF_system(band,n,hrs_mode,mixer_polarization,integ_time,backend,result[0]{0});
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
//HIFI-COP-1.2-HRS_FT
procedure HRS_FT_COP_proc_ops {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_comment("Start of HIFI HRS Functional Test");
//General parameters in use: use band 5
string band = "5a";
double lo_freq = 1122.0;
int integ_time = 4;
string backend = "hrs";
string[] hrs_mode = ["wb1","wb1"];
string laser_H = "Laser2";
string laser_V = "Laser2";
//
string hbb_heater = "ON";
//hot source on/off
string chopper_loop = "CLOSE";
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
if(chopper_loop == "OPEN") {
result = ConfigurationReader("name_chopper",["chop_startup_warm"],"0",0.0);
}
mois_step("Switch FPU band 5");
double chopper_voltage = result[0]{0};
Init_MSA_ops(band,chopper_loop,lo_freq,chopper_voltage,hbb_heater,prime_or_redundant);
mois_tmcheck("Check that parameter HF_DH1_MXBAND and HF_DV1_MXBAND are both 5");
//Set mixer bias to 5mV
mois_step("Turn on shot noise for band 5 mixers");
result = ConfigurationReader("name_confilfpu",["bias_low_resistive_h","bias_low_resistive_v"],band,0.0);
double bias_low_h = result[0]{0};
double bias_low_v = result[1]{0};
//Set magnets to 0
Set_Magnet_current_block_fm(0.0,0.0);
mois_tmcheck("Check that parameters HF_AH1_MXMG_C and HF_AV1_MXMG_C are both set to 0 mA");
//
Mixerbias(bias_low_h,bias_low_v);
mois_tmcheck("Check that parameters HF_AH1_MXBIAS_V and HF_AV1_MXBIAS_V are set to " + bias_low_h + " and " + bias_low_v + " mV respectively");
//
mois_step("HRS FT#1");
HRS_functional_test_No_1_block_fm();
//
mois_step("HRS to standby and tuning");
HRS_config_max_att_block_fm(band,hrs_mode);
HRS_tune_block_fm(band);
//To check final attenuator settings
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
Spectro_total_power_block_fm(band,[integ_time,1],backend);
//
mois_step("HRS FT#2 with square_s");
HRS_functional_test_No_2_Square_s_block_fm(band,hrs_mode,integ_time,backend);
//
mois_step("HRS FT#2 with square_m");
HRS_functional_test_No_2_Square_m_block_fm(band,hrs_mode,integ_time,backend);
//
mois_step("HRS FT#2 with sine");
HRS_functional_test_No_2_Sine_block_fm(band,hrs_mode,integ_time,backend);
//
mois_step("HRS FT#2 with correlation");
HRS_config_att_lo_block_fm(band,hrs_mode);
HRS_tune_block_fm(band);
HRS_functional_test_No_2_Corr_block_fm(band,hrs_mode,integ_time,backend);
//
mois_step("HRS FT#4");
HRS_functional_test_No_4_block_fm(band,hrs_mode,integ_time,backend);
//
mois_step("HRS linearity test");
HRS_linearity_indiv_block_cop(band,hrs_mode,integ_time,"hrs");
//
mois_step("HRS cross-polar");
HRS_polar_switch_proc_fm(band,hrs_mode);
//
mois_step("HRS tuning");
HRS_tune_block_fm(band);
//To check final attenuator settings
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
Spectro_total_power_block_fm(band,[integ_time,1],backend);
//
mois_step("Switch to FPU band 0");
Init_MSA_ops("0",chopper_loop,lo_freq,chopper_voltage,hbb_heater,prime_or_redundant);
}
/////////////////////////////////////////////////////////////////
// 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,imin(data_time,data_time_off));
{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,"fs");
int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0);
// 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,reffreq,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 = 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;
}
// 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;
}
// Additional constraint of compatibility of group size with load period
int loadperiod = LoadPeriod(band,reffreq,effResolution{1});
// 80% margin
int periodlimit = loadperiod * 4 / 5;
// elements of cycle - compute cycle duration
int tunedelay = LOSettlingTime(band,reffreq / 1000.0,false,true);
tunedelay = 2 * tunedelay;
int load_datatime = imax(data_time_guess,data_time_off_guess);
int loadlength = duration(SScanDoubleLoadMeasurement(band,reffreq,reffreq,freq_throw,true,effResolution{0},load_datatime,backendreadoutparms));
int perfreqtime = 2 * (data_time_guess * n_switch_on_guess + data_time_off_guess * n_switch_off_guess + tunedelay);
int cycle = perfreqtime * n_freq_point_guess + loadlength;
if(cycle > periodlimit) {
n_freq_point_guess = imax((periodlimit - loadlength) / perfreqtime,1);
}
int n_freq_point_range = 1 - n_freq_point_guess;
if(n_freq_point_range == 0) {
n_freq_point_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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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 Map fastChop",{data_time,0,n_switch_on,n_int_on,0,0,n_pointsperscan,0,n_cycles,load_interval});
ChopMessages(true,data_time,n_int_on);
RasterSizeMessages({0.0,0.0},stepsize,2,npoints,true);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
//Generic procedure for slowchop using the adequate instrument side
//It also converts prime voltage into redundant voltage
procedure HIFI_Spectr_fast_chop_proc_fm {
double chop_angle1 = 0.0;
double chop_angle2 = 0.0;
int n_wbs1 = 1;
int n_hrs_trans = 1;
}{
//Convert prime voltage into redundant voltage
chop_angle1 = Check_Chopper_Prime_Redundant(chop_angle1);
chop_angle2 = Check_Chopper_Prime_Redundant(chop_angle2);
//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_Spectr_fast_chop($BBID,chop_angle1,chop_angle2,n_wbs1,n_hrs_trans);
} else {
Hifi_HIFI_R_Spectr_fast_chop($BBID,chop_angle1,chop_angle2,n_wbs1,n_hrs_trans);
}
//
}
//HIFI-COP-X-Dip-FSW
obs HifiEng_Dip_FSW_COP {
string band = "3a" in ["3a","3b","4a","4b","6a","6b","7a","7b"]; // HIFI band
string polarization = "H" in ["H","V"]; //The polarization on which the test is done
int nb_pairs = 20; //number of FSW1-FSW2 pairs
int throw_index = 1; //index of FSW throw as of stab FSW table of throws
int freq_index = 1; //index of FSW throw as of stab FSW table of frequencies
bool retune = true; //whether the diplexer is adjusted between frequencies or not
}{
//General parameters in use
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
int integ_time = 4;
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Dip_FSW_COP_proc_ops(band,throw_index,freq_index,hrs_mode,integ_time,backend,nb_pairs,polarization,retune));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Dip_FSW_COP_proc_ops(band,throw_index,freq_index,hrs_mode,integ_time,backend,nb_pairs,polarization,retune);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
//HRS Functional Test #0, block: right after switch on, BEFORE HK collection
block HRS_functional_test_No_0_block_ops HIFI 7610 {
}{
mois_comment("Performing HRS Functional Test #0");
//Use new command implemented in SCR-859
Hifi_HIFI_HRS_functional_test($BBID,0,"BOTH");
delay(5);
//
}
// Take freq switch spectra, block
block Spectro_freq_switch_block_fm HIFI 3612 {
string band = "1a"; // HIFI band
int[] timing_parms = [4,2]; //single readout time in sec. and n_wbs_start
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
//Start_block();
//Compute data-rate
int integ_time = timing_parms[0] * timing_parms[1];
double[] rates = ILT_datarate_proc_fm(band,backend,"fsw",integ_time);
//Take spectrum
// set data rates
non_ess_hk_data_rate(rates[2] / 1024.0);
data_rate(rates[0] / 1024.0);
//
Hifi_HIFI_Spectr_freq_switch($BBID);
Apply_Slow_Chop_delay(integ_time,band,backend);
// reset data rates
non_ess_hk_data_rate(rates[1] / 1024.0);
data_rate(0.0);
}
//////////////////////////////////////////////////////////////////////
// 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);
}
//HIFI-COP-3-Deflux
//Systematic deflux at beginning of each OD, or band switch
procedure Deflux_COP_proc_ops {
string band = "1a" in ["ALL","1a","1b","2a","2b","3a","3b","4a","4b"]; // HIFI band. ALL does all mixer bands
}{
if(band != "ALL") {
Deflux_SingleBand_proc_ops(band);
} else {
Deflux_SingleBand_proc_ops("1a");
Deflux_SingleBand_proc_ops("2a");
Deflux_SingleBand_proc_ops("3a");
Deflux_SingleBand_proc_ops("4a");
}
}
//Transition mode to Dissipative 1
mode HifiManCmdSetIntoDissipative_I {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to transit to Dissipative 1");
StartMode_block_ops();
//
mois_step("Switch to dissipative 1 mode");
HifiSetIntoDissipative_I_mois();
//
StopMode_block_mois();
}
/////////////////////////////////////////////////////////////////
// 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};
{{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,"lchop");
int n_freq_point_guess = ifloor(nocaliblen / (stdstep * double(increment)) + 1.0);
// 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);
// Additional constraint of compatibility of group size with load period
int loadperiod = LoadPeriod(band,reffreq,effResolution{1});
// 80% margin
int periodlimit = loadperiod * 4 / 5;
// elements of cycle - compute cycle duration
int tunedelay = LOSettlingTime(band,reffreq / 1000.0,false,true);
int load_datatime = iceil(retvalues[0]{1});
int loadlength = duration(SScanLoadMeasurement(band,reffreq,reffreq,true,effResolution{0},load_datatime,backendreadoutparms));
int perfreqtime = 2 * load_datatime + tunedelay;
int cycle = perfreqtime * n_freq_point_guess + loadlength;
if(cycle > periodlimit) {
n_freq_point_guess = imax((periodlimit - loadlength) / perfreqtime,1);
}
int n_freq_point_range = 1 - n_freq_point_guess;
if(n_freq_point_range == 0) {
n_freq_point_range = 1;
}
retvalues[1] = {"n_freq_point",double(n_freq_point_guess),double(n_freq_point_range)};
return retvalues;
}
//HIFI-COP-1.2-WBS_FT
procedure WBS_FT_COP_proc_ops {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_comment("Start of HIFI WBS Functional Test");
//General parameters in use
string band = "0";
int integ_time = 4;
string backend = "wbs";
double lo_freq = 500.0;
//0. Ensure band0: no IF input power
string hbb_heater = "ON";
//hot source on/off
string chopper_loop = "CLOSE";
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
if(chopper_loop == "OPEN") {
result = ConfigurationReader("name_chopper",["chop_startup_warm"],"0",0.0);
}
mois_step("FPU set to band0");
Init_MSA_ops(band,chopper_loop,lo_freq,result[0]{0},hbb_heater,prime_or_redundant);
mois_tmcheck("Check that parameter HF_DH1_MXBAND and HF_DV1_MXBAND are both 0");
//
string laser_H = "Lasers_off";
string laser_V = "Lasers_off";
//
//1. Zero w/o laser
mois_step("WBS Zero without Laser");
WBS_config_w_laser_block_fm(band,laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_Laser1_S, HWH_Laser2_S, HWV_Laser1_S and HWV_Laser2_S are all OFF");
WBS0_fm(band);
WBS0_fm(band);
//2. WBS FT
//Configure WBS laser according to user inputs.
laser_H = "Laser1";
laser_V = "Laser1";
mois_step("Configure WBS with Laser 1");
WBS_config_w_laser_block_fm(band,laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_Laser1_S and HWV_Laser1_S are ON");
//Wait 2 minutes for laser stabilization
mois_comment("wait 2 minutes for stabilization");
delay(120);
//Do zero
mois_step("WBS Zero with Laser 1");
WBS0_fm(band);
//Do zero and COMB
mois_step("WBS Comb with Laser 1");
WBS_calib_fm(band);
// Configure spectroscopy
mois_step("Attenuator scans with Laser 1");
Configure_Spectrometer_proc_fm(band,integ_time,["wb1","wb1"],backend);
//Set att. to min. and take spectrum
WBS_config_min_att_w_laser_block_fm(band,laser_H,laser_V);
Spectro_total_power_block_fm(band,[integ_time,1],backend);
//Scan all attenuators to get attenuator steps
FT_WBS_att_overall_fm(band,integ_time,laser_H,laser_V,backend);
FT_WBS_att_individual_fm(band,integ_time,laser_H,laser_V,backend);
//3. Linearity test
mois_step("WBS linearity test with Laser 1");
FT_WBS_linearity(band,integ_time,laser_H,laser_V,backend);
//4. Lacthup test
mois_step("WBS latchup test with Laser 1");
WBS_set_Latchup_block_fm(band,"high",laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_LUP_level_S and HWV_LUP_level_S are both High");
WBS_set_Latchup_block_fm(band,"low",laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_LUP_level_S and HWV_LUP_level_S are both Low");
//5. Tuning
mois_step("WBS tuning with Laser 1");
band = "5a";
lo_freq = 1122.0;
Init_MSA_ops(band,chopper_loop,lo_freq,result[0]{0},hbb_heater,prime_or_redundant);
mois_tmcheck("Check that parameter HF_DH1_MXBAND and HF_DV1_MXBAND are both 5");
WBS_tune_proc_fm(band);
//To check final attenuator settings
Configure_Spectrometer_proc_fm(band,integ_time,["wb1","wb1"],backend);
Spectro_total_power_block_fm(band,[integ_time,1],backend);
//
//Repeat with laser 2
laser_H = "Laser2";
laser_V = "Laser2";
//
//
mois_step("FPU set to band0");
band = "0";
lo_freq = 500.0;
Init_MSA_ops(band,chopper_loop,lo_freq,result[0]{0},hbb_heater,prime_or_redundant);
mois_tmcheck("Check that parameter HF_DH1_MXBAND and HF_DV1_MXBAND are both 0");
//2. WBS FT
//Configure WBS laser according to user inputs.
mois_step("Configure WBS with Laser 2");
WBS_config_w_laser_block_fm(band,laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_Laser2_S and HWV_Laser2_S are ON");
//Wait 2 minutes for laser stabilization
mois_comment("wait 2 minutes for stabilization");
delay(120);
//Do zero
mois_step("WBS Zero with Laser 2");
WBS0_fm(band);
//Do zero and COMB
mois_step("WBS Comb with Laser 2");
WBS_calib_fm(band);
// Configure spectroscopy
mois_step("Attenuator scans with Laser 2");
Configure_Spectrometer_proc_fm(band,integ_time,["wb1","wb1"],backend);
//Set att. to min. and take spectrum
WBS_config_min_att_w_laser_block_fm(band,laser_H,laser_V);
Spectro_total_power_block_fm(band,[integ_time,1],backend);
//Scan all attenuators to get attenuator steps
FT_WBS_att_overall_fm(band,integ_time,laser_H,laser_V,backend);
FT_WBS_att_individual_fm(band,integ_time,laser_H,laser_V,backend);
//3. Linearity test
mois_step("WBS linearity test with Laser 2");
FT_WBS_linearity(band,integ_time,laser_H,laser_V,backend);
//4. Lacthup test
mois_step("WBS latchup test with Laser 2");
WBS_set_Latchup_block_fm(band,"high",laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_LUP_level_S and HWV_LUP_level_S are both High");
WBS_set_Latchup_block_fm(band,"low",laser_H,laser_V);
mois_tmcheck("Check that parameters HWH_LUP_level_S and HWV_LUP_level_S are both Low");
//5. Tuning
mois_step("WBS tuning with Laser 2");
band = "5a";
lo_freq = 1122.0;
Init_MSA_ops(band,chopper_loop,lo_freq,result[0]{0},hbb_heater,prime_or_redundant);
mois_tmcheck("Check that parameter HF_DH1_MXBAND and HF_DV1_MXBAND are both 5");
WBS_tune_proc_fm(band);
//To check final attenuator settings
Configure_Spectrometer_proc_fm(band,integ_time,["wb1","wb1"],backend);
Spectro_total_power_block_fm(band,[integ_time,1],backend);
//
//At the end, switch back to laser1 - HIFI-3584
mois_step("Configure WBS with Laser 1");
laser_H = "Laser1";
laser_V = "Laser1";
WBS_config_w_laser_block_fm(band,laser_H,laser_V);
}
// 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};
}
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);
}
// Broadcast OBSID
block BroadcastOBSID HIFI 900 {
}{
//These are ILT-EGSE commands, not ruled by the 2TC/sec.
//HifiIltEgse_PDU_set_OBS_ID($OBSID);
//HifiIltEgse_PDU_set_BB_ID($BBID);
//delay(1);
//HifiIltEgse_FPU_set_OBS_ID($OBSID);
//HifiIltEgse_FPU_set_BB_ID($BBID);
//delay(1);
//SpireIltEgse_QCC_SETOBSID($OBSID);
//SpireIltEgse_QCC_SETBBID($BBID);
//delay(1);
Hifi_HIFI_Set_OBS_ID($BBID,$OBSID);
Hifi_HIFI_non_periodic_hk_FCU();
delay(1);
}
// 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]);
}
//LCU IV curves, block
//The LO needs to be switched off prior to the IV curve
block Measure_LCU_IV_block_fm HIFI 3663 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string multiplier = "M1" in ["M1","M2","M3"]; //Multiplier to be measured: M1, M2 or M3
}{
//
//Start_block();
//Translate band name
string band_new = Translate_band_name(band);
string multiplier_code = multiplier + "_" + band_new;
//
{double,string}[] result = ConfigurationReader("name_delays",["lcu_iv_delay_m1","lcu_iv_delay_m2","lcu_iv_delay_m3"],"0",0.0);
int lcu_iv_delay_m1 = iround(result[0]{0});
int lcu_iv_delay_m2 = iround(result[1]{0});
int lcu_iv_delay_m3 = iround(result[2]{0});
//For M2_6b, 7a and 7b, we need 19 sec. more
if(multiplier == "M2" && (band == "6b" || band == "7a" || band == "7b")) {
lcu_iv_delay_m2 = lcu_iv_delay_m2 + 19;
}
if(multiplier == "M3" && band == "3b") {
lcu_iv_delay_m3 = lcu_iv_delay_m3 + 11;
}
//We will use this delay as input for the TC.
//Check M3 not called for inadequate bands
bool go_ahead = true;
if(multiplier == "M3" && band != "2a" && band != "2b" && band != "3a" && band != "3b" && band != "6a") {
go_ahead = false;
}
if(go_ahead) {
if(multiplier == "M1") {
Hifi_HIFI_measure_LCU_IV($BBID,multiplier_code,lcu_iv_delay_m1);
delay(lcu_iv_delay_m1);
}
if(multiplier == "M2") {
Hifi_HIFI_measure_LCU_IV($BBID,multiplier_code,lcu_iv_delay_m2);
delay(lcu_iv_delay_m2);
}
if(multiplier == "M3") {
Hifi_HIFI_measure_LCU_IV($BBID,multiplier_code,lcu_iv_delay_m3);
delay(lcu_iv_delay_m3);
}
// allow for the OBS to collect data AdJ 18-apr-2008
delay(2);
}
//
}
//Go into dissipative1 in MTL
obs HifiEng_SetIntoDissipative_I_MTL {
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Set_LO_Dissipative_block_aot()) + duration(Set_LO_Nominal_block_aot());
// 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) {
// Test execution
Set_LO_Nominal_block_aot();
Set_LO_Dissipative_block_aot();
}
if(state[0] == 5) {
//HIFISetHK("normal",true); // -> superfluous
HIFICloseObs();
}
}
}
//HIFI-COP-3-Tsys + Vecscan with M1V control
obs HifiEng_Tsys_Vecscan_M1_COP {
string band = "1a" in ["1a","5a","5b","7b"]; // HIFI band
}{
//General parameters in use
int integ_time = 4;
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
int n_wbs1 = 0;
int n_hrs_trans = 0;
string chopmode = "slowchop";
//For bands 6 and 7, use wb8
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
hrs_mode = ["wb8","wb8"];
}
//
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Tsys_Vecscan_M1_COP_proc_ops(band,integ_time,backend,hrs_mode,n_wbs1,n_hrs_trans,chopmode));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Tsys_Vecscan_M1_COP_proc_ops(band,integ_time,backend,hrs_mode,n_wbs1,n_hrs_trans,chopmode);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
HIFICloseObs();
}
}
}
// Procedure to compute the parameters needed in a Chopped HRS fast measurement
block Stability_chopped_fasthrs_block_ops HIFI 3440 {
/* Integration time */
string band = "1a"; // HIFI band
double lo_freq = 522.0; // LO frequency
int data_time = 10; // Chop phase length
int n_data = 10; // Number of phases
double hrs_readout = 0.333; // HRS readout length
string chopper_pair = "load" in ["load","sky"]; //internal load or sky on-off
}{
// Fixed backend configuration
// No WBS
int wbsh_offset1 = 0;
int wbsh_width1 = 0;
int wbsh_offset2 = 2048;
int wbsh_width2 = 0;
int wbsh_offset3 = 4096;
int wbsh_width3 = 0;
int wbsh_offset4 = 6144;
int wbsh_width4 = 0;
int wbsv_offset1 = 0;
int wbsv_width1 = 0;
int wbsv_offset2 = 2048;
int wbsv_width2 = 0;
int wbsv_offset3 = 4096;
int wbsv_width3 = 0;
int wbsv_offset4 = 6144;
int wbsv_width4 = 0;
string packing = "24_bits_format";
// HRS
int hrsh_sel = 128;
//10000000 = 1U only
int hrsv_sel = 128;
//10000000 = 1U only
// No bitshift
int hrs_rshift = 0;
int wbs_rshift = 0;
// Timing - copied from ConfigSpectroscopyParams
// 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 given by switch dead time
double res = GetLoadChopDeadTime(band,lo_freq);
// minimum delay
int 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","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[7]{0});
int wbs_chunksize = iround(result[4]{0});
int tacc_add = iround(result[5]{0});
int min_wbs_acc = iround(result[6]{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
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;
// No WBS addition in ICU
int n_wbs_integr = 1;
int n_wbs_start = n_data;
// HRS
int hrs_phase = iceil(1000.0 * hrs_readout);
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 = 1;
// Issue configuration
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_offset1,wbsh_width1,wbsh_offset2,wbsh_width2,wbsh_offset3,wbsh_width3,wbsh_offset4,wbsh_width4,wbsv_offset1,wbsv_width1,wbsv_offset2,wbsv_width2,wbsv_offset3,wbsv_width3,wbsv_offset4,wbsv_width4,hrs_rshift,wbs_rshift,hrsh_sel,hrsv_sel,packing);
//
// Now call the spectroscopy
//Get appropriate chopper voltages
{bool,double,double} chopparms = GetChopVoltages(band,lo_freq,"chop_hot","chop_cold");
if(chopper_pair == "sky") {
chopparms = GetChopVoltages(band,lo_freq,"chop_M3right","chop_M3left");
}
bool isPrime = chopparms{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(n_data * data_time + 3);
}
/////////////////////////////////////////////////////////////////
// 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
string refmode = "dbs" in ["dbs","fs","lchop"]; // reference scheme to use
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,refmode);
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
// adjust reference frequency to be within the grid
gfref = GetFReference(band,freqgrid[0],freqgrid[nfreq - 1]);
reffreq = gfref{0};
// 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 + "
");
message("Frequency used for noise computation: " + reffreq / 1000.0 + "GHz.
");
// 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;
}
}
// 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);
//
}
//Fast HK measurement on LCU power
obs HifiEng_Fast_LCU_HK_COP {
string hkrate = "1_pkt_per_3_s" in ["1_pkt_per_10_s","1_pkt_per_3_s","1_pkt_per_4_s","1_pkt_per_s","1_pkt_per_5_s"]; // HIF_HK_rate;
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Fast_LCU_HK_COP_proc_ops(hkrate));
// 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("normal",true);
}
if(state[0] == 3) {
// Test execution
Fast_LCU_HK_COP_proc_ops(hkrate);
}
if(state[0] == 5) {
//HIFISetHK("normal",true);
StopMode_block_ops();
}
}
}
// 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
int theindex = 0;
for(int i = 0 .. n_cycles - 1) {
for(int i1 = 0 .. n_loadnods - 1) {
theindex = theindex + n_loadinterval * 2 * scansize;
if(theindex < numpoints) {
longslew = imin(longslew,telescopetimes[theindex + 6]);
}
}
}
return longslew;
}
// WBS attenuator tuning, procedure
// Both polarizations are treated
procedure WBS_tune_proc_fm {
string band = "1a"; // 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.
WBS_tune_block_fm(band,tune_target);
//
}
//Set LCU4b back to standby status, procedure
procedure LCU4b_standby_proc_fm {
string band = "4b"; // HIFI band
double lo_freq = 1100.0 in [1056.0,1113.0]; //LO frequency
}{
error("This module is obsolete: use LCU_standby_proc_fm instead");
}
// Step 1 of QLA_Testcontrol coarse magnet-tuning loop
// Bias current at low bias
block Magnet_scan_coarse_fm HIFI 3201 {
string band = "1a";
}{
Start_block();
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["magnet_current_min_h","magnet_current_max_h","magnet_steps_h","magnet_step_duration_h","bias_very_low_h","magnet_current_min_v","magnet_current_max_v","magnet_steps_v","magnet_step_duration_v","bias_very_low_v"],band,0.0);
//H polar
double magnet_min_h = result_d[0]{0};
double magnet_max_h = result_d[1]{0};
int steps_h = iround(result_d[2]{0});
double step_time_h = result_d[3]{0};
double bias_h = result_d[4]{0};
//V polar
double magnet_min_v = result_d[5]{0};
double magnet_max_v = result_d[6]{0};
int steps_v = iround(result_d[7]{0});
double step_time_v = result_d[8]{0};
double bias_v = result_d[9]{0};
//
double step_time = max(step_time_h,step_time_v);
//
Magnet_scan(band,magnet_min_h,magnet_max_h,steps_h,step_time,bias_h,magnet_min_v,magnet_max_v,steps_v,bias_v);
}
//HIFI Housekeeping ON, block
//I set 1 fixed rate of 1 packet per sec.
block HIFI_Housekeeping_on_block_fm HIFI 3656 {
}{
Start_block_no_hk_request();
//Get applicable HK rate
{double,string}[] result_d = ConfigurationReader("name_delays",["hk_rate"],"0",0.0);
string hk_rate = result_d[0]{1};
Hifi_HIFI_Housekeeping_on(hk_rate,"ON","ON","ON","ON","ON","ON");
delay(1);
}
//HIFI-COP-7.1-FT: Regular FT during Commissioning for Temp. trend monitoring
procedure TrendMon_FT_COP_proc_ops {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
string[] band = ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"];
//
//1. FT unpumped
//General parameters in use
int integ_time = 4;
string backend = "both";
string[] hrs_mode = ["wb1","wb1"];
for(int i = 0 .. 6) {
//For bands 6 and 7, use wb8
if(band[2 * i] == "6a" || band[2 * i] == "7a") {
hrs_mode = ["wb8","wb8"];
}
FT_unpumped(band[2 * i],hrs_mode,integ_time,backend);
}
//2. IF feeb-back in one band: band 5a
double lo_freq = 1116.0;
hrs_mode = ["wb1","wb1"];
integ_time = 604;
IF_FBk_COP_proc_ops(band[8],lo_freq,hrs_mode,integ_time,backend);
//3. IF stability in one SIS band: band 1a
int n = 751;
//Number of load pairs to be measured
string mixer_polarization = "B";
//Polarization: H, V, or both (B)
integ_time = 4;
//Use high biases
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_high_resistive_h"],band[0],0.0);
Proc_stability_IF_system(band[0],n,hrs_mode,mixer_polarization,integ_time,backend,result[0]{0});
//Repeat for band 6a
result = ConfigurationReader("name_confilfpu",["bias_high_resistive_h"],band[10],0.0);
Proc_stability_IF_system(band[10],n,hrs_mode,mixer_polarization,integ_time,backend,result[0]{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";
// We chop now from plusZ tu minusZ, i.e. in negative direction
// The nodding has to go into the opposite direction
double[] nodpatt = CalibrationReader("skychopthrow",[lstring,astring],band,lo_freq);
// restrict to allowed range
double patt = (nodpatt[1] + 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();
}
}
}
//OBS autonomous function against LCU loss of communication - SCR-3099
mode HifiManCmd_LCU_comm_FDIR_disable {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to disable check of LCU loss communication");
//StartMode_block_ops();
//
mois_spacon("Verify that HM125190 (HI_au_LCUresp_S) is ON");
mois_step("Disable LCU loss of communication watchdog function");
Disable_LCU_comm_FDIR_block_mois();
//
mois_spacon("Verify that HM125190 (HI_au_LCUresp_S) is OFF");
StopMode_block_mois();
}
// Very fast sampling stability measurement combined with int-load-chop
// Uses only the HRS in wb mode
procedure Stability_chopped_fasthrs_proc_ops {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 522.0; // LO frequency
int phaselength = 10; // Chop phase length
int nchop = 10; // Number of phases
double readout = 0.333; // HRS readout length
double[] hrs_subband = [5.0,5.0,5.0,5.0]; //Positions in IF of HRS sub-bands
string chopper_pair = "load" in ["load","sky"]; //internal load or sky on-off
string polarization = "B"; //mixer to be sampled: H, V or B. If B, they are done successively
int milliSecSample = 3; // interval between samples
int samplesBefore = 50;
int samplesAfter = 1000;
string with_lo_on = "true" in ["true","false"]; //Whether measurement with LO ON or not
}{
// Clean HK treatment for controlled data rates
HIFISetHK("fast",false);
{string,int,double,double,double,double} hkparms = PeriodicHKParms("fast");
// HK data: stdrate=7744+864+2*272, IF packets=2*(592+272)
int allhkbits = 1782;
double hkrate = hkparms{3} + double(allhkbits) / readout;
// Science data: 2*(2*258*24+1376+3*272)
int allbits = 29152;
double sciencerate = double(allbits) / readout;
// set data rates
ess_hk_data_rate(hkparms{5} / 1024.0);
non_ess_hk_data_rate(hkrate / 1024.0);
data_rate(sciencerate / 1024.0);
//Configure HRS: regardless of selected bands
HRS_config_resol_block_fm(band,["wb1","wb1"]);
HRS_config_att_lo_w_lo_input_block_fm(band,["wb1","wb1"],hrs_subband);
//Prepare chopper position for HRS attenuator tuning
if(chopper_pair == "load") {
Chopper_Rotation_block_fm(band,"chop_M3_ang","chop_hot_ang");
//Look at HBB
} else {
Chopper_Rotation_block_fm(band,"chop_hot_ang","chop_M3_ang");
//Look at sky
}
//measurement without LO
if(with_lo_on == "false") {
//Force LO swith-off
LCU_switch_off_block_fm();
//FPU configuration
if(chopper_pair == "load") {
Init_MSA_HBB_fm(band,"CLOSE",lo_freq,"ON");
} else {
Init_MSA_SKY_fm(band,"CLOSE",lo_freq,"ON");
}
//For HEBs, set bias to 3mV
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilfpu",["bias_max_h","bias_max_v"],band,lo_freq);
Mixerbias_block_fm(result[0]{0},result[1]{0});
result = ConfigurationReader("name_confilfpu",["bias_dipscan_h","bias_dipscan_v"],band,lo_freq);
Mixerbias_block_fm(result[0]{0},result[1]{0});
}
//Fast Imix measurement: only if option load
if(chopper_pair == "load") {
Fast_Imix_block_fm(band,polarization,milliSecSample,samplesBefore,samplesAfter);
}
//Backend tuning without LO
HRS_tune_block_fm(band);
// Run the actual chopped fast-HRS interation
Stability_chopped_fasthrs_block_ops(band,lo_freq,phaselength,nchop,readout,chopper_pair);
} else {
//measurement with LO
//LO swith-on
LCU_switchon_proc_fm(band);
//Wait an extra delay of 1 min for short term stabilization
delay(60);
//FPU configuration
if(chopper_pair == "load") {
Init_MSA_HBB_fm(band,"CLOSE",lo_freq,"ON");
} else {
Init_MSA_SKY_fm(band,"CLOSE",lo_freq,"ON");
}
//LO tuning
LO_tuning_block_fm(band,lo_freq);
//Fast Imix measurement: only if option load
if(chopper_pair == "load") {
Fast_Imix_block_fm(band,polarization,milliSecSample,samplesBefore,samplesAfter);
}
//Backend tuning with LO
HRS_tune_block_fm(band);
// Run the actual chopped fast-HRS interation
Stability_chopped_fasthrs_block_ops(band,lo_freq,phaselength,nchop,readout,chopper_pair);
}
// reset data rates
non_ess_hk_data_rate(hkparms{3} / 1024.0);
data_rate(0.0);
}
// IV curve, block
block IVcurve_general_fm HIFI 3210 {
string band = "1a";
double lo_freq = 522.0; //LO frequency
double bias_min = -6.0;
double bias_max = 6.0;
int steps = 131;
}{
//Start_block() ;
//Fetch values for magnets and bias
if(band == "0") {
{double,string}[] result_d = ConfigurationReader("name_confilfpu",["bias_standby_h","bias_standby_v","magnet_standby_h","magnet_standby_v"],band,0.0);
} else {
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
result_d = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v","norm_magn_h","norm_magn_v"],band,lo_freq);
} else {
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};
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
double magnet_current_h = result_d[2]{0};
double magnet_current_v = result_d[3]{0};
} else {
magnet_current_h = 0.0;
magnet_current_v = 0.0;
}
//
IVcurve(band,bias_min,bias_max,steps,magnet_current_h,magnet_current_v,bias_h,bias_v);
}
////////////////////////////////////////
// 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];
}
// Initialisation of FPU, block with both MSA in use
// It is for warm context !
block Init_MSA_fm_dummy HIFI 3220 {
string band = "1a"; // HIFI band
string chop_loop = "CLOSE";
double lo_freq = 522.0; //LO frequency
}{
Start_block();
//Get parameters
{double,string}[] result_d = ConfigurationReaderWarm("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 = ConfigurationReaderWarm("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 = ConfigurationReaderWarm("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};
//
//Get biases
result_d = ConfigurationReaderWarm("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};
//
//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 = ConfigurationReaderWarm("name_confilmix",["norm_magn_h","norm_magn_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 = ConfigurationReaderWarm("name_confilfpu",["diplex_h_ctrl_mode","diplex_v_ctrl_mode","diplexer_current_normal_h","diplexer_current_normal_v"],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_d[2]{0};
//result_dip[0];
diplex_V = result_d[3]{0};
//result_dip[1];
}
//
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.
//chopper = Check_Chopper_Prime_Redundant(chopper);
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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 = ConfigurationReaderWarm("name_delays",["config_fpu_delay"],band,lo_freq);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
Hifi_HIFI_non_periodic_hk_FCU();
}
// WBS stand-by, block
block WBS_standby_fm HIFI 3703 {
string band = "1a"; // HIFI band
string laser_H = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2","Lasers_off"]; //WBS-V laser to be set ON
}{
//Start_block();
//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
//
string hwh_laser1_s = "OFF";
string hwh_laser2_s = "OFF";
if(laser_H == "Laser1") {
hwh_laser1_s = "ON";
}
if(laser_H == "Laser2") {
hwh_laser2_s = "ON";
}
int hwh_heater = 0;
//000
string hwh_latchup_s = "Level1";
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"],band,0.0);
int wbs_config_delay = iround(result[0]{0});
//delay(wbs_config_delay); //Wait for configuration to be applied
//
//V-Polarization
//
string hwv_laser1_s = "OFF";
string hwv_laser2_s = "OFF";
if(laser_V == "Laser1") {
hwv_laser1_s = "ON";
}
if(laser_V == "Laser2") {
hwv_laser2_s = "ON";
}
int hwv_heater = 0;
//000
string hwv_latchup_s = "Level1";
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
//
}
/////////////////////////////////////////////////////////////////
// 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];
}
//Notify PDU status ON, block
//I assume all S/S are present
block HIFI_notify_PDU_status_on_block_fm HIFI 3655 {
string status_FCU = "ON" in ["ON","OFF"]; //Status of FCU
string status_LCU = "ON" in ["ON","OFF"]; //Status of LCU
string status_WBSV = "ON" in ["ON","OFF"]; //Status of WBSV
string status_WBSH = "ON" in ["ON","OFF"]; //Status of WBSH
string status_HRSV = "ON" in ["ON","OFF"]; //Status of HRSV
string status_HRSH = "ON" in ["ON","OFF"]; //Status of HRSH
}{
Start_block_no_hk_request();
Hifi_HIFI_notify_PDU_status(status_FCU,status_LCU,status_WBSV,status_WBSH,status_HRSV,status_HRSH);
delay(1);
}
// WBS comb, block
block WBS_comb_fm HIFI 3605 {
string band = "1a"; // HIFI band
}{
//Start_block();
//Two options are possible: CUS sequence or automatic OBS command
//Option1: CUS sequence
//WBS_comb_fm_proc(band,backend);
//Option2: OBS command. It takes attenuators as input as well.
//We have to set attenuators to values different from max.
//Initial configuration
//H-Polarization
//
{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});
//
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);
//Apply delay
result_d = ConfigurationReader("name_delays",["wbs_comb_delay"],band,0.0);
int wbs_comb_delay = iround(result_d[0]{0});
delay(wbs_comb_delay);
//
}
//Load new OBSW , block
block Load_OBSW_block_ops HIFI 7927 {
}{
mois_comment("Assign obsid number to procedure execution");
mois_spacon("In the following command, the second parameter (OBS_ID) shall be replaced by a Formal Parameter value according to the list provided by the instrument ICC.");
Hifi_HIFI_Set_OBS_ID($BBID,$OBSID);
//
mois_step("Construct the OBSW copy");
mois_spacon("Use the OBSM to prepare the HIFI_load_PRAM TC list to build the new version of the OBSW that is to be loaded and started");
//
mois_step("Upload the OBSW copy to PM-high");
mois_spacon("Use the OBSM to run the TC list previously prepared to load the new version of the OBSW. Please be aware at the copy should start from address 0x3ffff.");
//
mois_step("Verify integrity of copied OBSW: three checks are involved");
//Check PM memory for OBS 6.2.1: need to put offsets of starting address for PM high
mois_spacon("In the following command, the three parameters will be replaced by Formal Parameters provided by the instrument ICC.");
int check_start = 0x3ffff + 0x3ffff;
int check_end = 0x400fe + 0x3ffff;
int check_crc = 0x9598;
Hifi_HIFI_check_PM_memory(check_start,check_end,check_crc);
delay(3);
mois_spacon("Checks that no (1,8) has been generated");
//
check_start = 0x43fff + 0x3ffff;
check_end = 0x454f1 + 0x3ffff;
check_crc = 0xf5f7;
Hifi_HIFI_check_PM_memory(check_start,check_end,check_crc);
delay(3);
mois_spacon("Checks that no (1,8) has been generated");
//
check_start = 0x454ff + 0x3ffff;
check_end = 0x5852a + 0x3ffff;
check_crc = 0x9793;
Hifi_HIFI_check_PM_memory(check_start,check_end,check_crc);
delay(3);
mois_spacon("Checks that no (1,8) has been generated");
//
mois_step("Dis-activate HK polling before copying new S/W to DM-low");
HIFI_notify_PDU_status_off_proc_ops("OFF","OFF","OFF","OFF","OFF","OFF");
//
mois_step("Copying uploaded OBSW to DM-low");
int hifi_OBS_destination = 0x3ffff;
// OBS_destination: start of PM high
int hifi_OBS_copy_length = 0x20000;
// OBS_copy_length
Hifi_HIFI_copy_mem_to_low(hifi_OBS_destination,hifi_OBS_copy_length);
delay(1);
//The new OBSW should be booted
mois_tmcheck("Check that the new OBSW release numbers have been updated (HI_SW_Version, HI_SW_Revision and HI_SW_Patch)");
//
mois_step("Re-activate HK polling before copying new S/W to DM-low");
HIFI_notify_PDU_status_on_proc_ops("ON","ON","ON","ON","ON","ON","ALL");
}
// 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);
}
//////////////////////////////////////////////////////////////////////
// Compatibility procedure to provide the same API as used in
// the previous versions
//
// Returns the actual integration time and the dead time per phase
{{double,double,double},{int,int}} procedure ConfigSpectroscopyFastChop {
/* Integration time */
double data_chop = 0.5 in [0.1,2.0]; // Length of a single chop phase
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 = "1a"; // HIFI band
double lo_freq = 522000.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}
}{
// Translate data_chop into new parameter data_time (approximate)
// Get auxiliary quantities
{double,string}[] result = ConfigurationReader("name_delays",["add_wbs","add_jitter","wbs_readout","wbs_init","scos_jitter"],band,lo_freq);
int add_wbs = iround(result[0]{0});
int add_jitter = iround(result[1]{0});
int wbs_readout = iround(result[2]{0});
int wbs_init = iround(result[3]{0}) + iround(result[4]{0});
int tdead_data = 2 * (wbs_readout + add_jitter) + add_wbs - add_jitter;
int totaltime = (iceil(1000.0 * data_chop) * 2 * n_int + tdead_data) * n_data + wbs_init;
totaltime = iceil(double(totaltime) / 1000.0);
int data_time = (totaltime + n_data - 1) / n_data;
// Check
CheckFastChopFrequency(band,lo_freq,data_time,n_int,n_data);
// 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 tdead_chop = timing{10};
tdead_data = timing{11};
int tint_act = timing{12};
{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);
//
// Return dead times and comand parameters
return {{double(tint_act) / 1000.0,double(tdead_chop) / 1000.0,double(data_time * n_data)},{n_wbs1,n_hrs_trans}};
}
//////////////////////////////////////////////////////////////////////////////
// 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);
}
// =======================================================
// These are the CUS by Moncef - extracted from the CUS
// import done by Albrecht.
// Modifications wrt Albrecht´s corrections:
// - I have suppressed all the capital letters in order to
// be compatible with the name in the configuration files
// - Some BBID are already used by other blocks. I set
// everything to 1501 upwards.
// DT - 24 Sept 2004
// 29 Sept 2004: Remark: nothing is done for V polar !
// 18 July 2005: Adapted for FM - both polar treated
// ========================================================
//Modes: see fm_testmodes.cus
//========================================================
// BLOCKS
//========================================================
// BLOCK : Functional Test No 0 (HRS Switch ON)
block HRS_functional_test_No_0_block_fm HIFI 3610 {
}{
//Start_block();
//
//Use new command implemented in SCR-859
Hifi_HIFI_HRS_functional_test($BBID,0,"BOTH");
delay(5);
//
}
// LCU5b configuration and tuning, procedure
procedure LCU5b_config_tune_proc_fm {
string band = "5b"; // HIFI band
double lo_freq = 1200.0 in [1192.0,1242.0]; //LO frequency
double drain_2_factor = 100.0; //Percentage factor of the targetted drain voltage
}{
error("This module is obsolete: use LO_tuning_block_fm instead");
}
//////////////////////////////////////////////////////////////////////
// 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,true);
}
//HIFI investigation of spurs in 1a and 4b
obs HifiEng_Spur_Investigation_COP {
string band = "1a" in ["1a","4b"]; // HIFI band
int freq_index = 1 in [0,3]; //Frequency index:
string parm = "G1" in ["G1","G2","D1","D2","M1","M2"]; //Parameter to scan: G1,G2,D1,D2,M1,M2
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band,"both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Spur_Investigation_proc_fm_COP(band,freq_index,parm));
// 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();
HIFILCUChecksumAndSetHK(band,"fast",true);
}
if(state[0] == 3) {
// Test execution
Spur_Investigation_proc_fm_COP(band,freq_index,parm);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band,false,"normal",true);
StopMode_block_ops();
}
}
}
//General LO configuration command
block HIFI_Configure_LCU_ALL_block_fm HIFI 3670 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //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);
//
//Start_block();
//
//Execute configuration
//Check which LO band is used
if(band == "1a") {
//Band 1a
Hifi_HIFI_Conf_nom_LCU_ch1a($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 == "1b") {
//Band 1b
Hifi_HIFI_Conf_nom_LCU_ch1b($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 == "2a") {
//Band 2a
Hifi_HIFI_Conf_nom_LCU_ch2a($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 == "2b") {
//Band 2b
Hifi_HIFI_Conf_nom_LCU_ch2b($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 == "3a") {
//Band 3a
Hifi_HIFI_Conf_nom_LCU_ch3a($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 == "3b") {
//Band 3b
Hifi_HIFI_Conf_nom_LCU_ch3b($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 == "4a") {
//Band 4a
Hifi_HIFI_Conf_nom_LCU_ch4a($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 == "4b") {
//Band 4b
Hifi_HIFI_Conf_nom_LCU_ch4b($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 == "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);
//
//Store settings into available register
HIFI_HL_store_tm_only_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//HIFI-COP-7.1-FT: Regular FT during Commissioning for Temp. trend monitoring
obs HifiEng_TrendMon_FT_COP {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing("0","none");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(TrendMon_FT_COP_proc_ops(prime_or_redundant));
// 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) {
// Test execution
TrendMon_FT_COP_proc_ops(prime_or_redundant);
}
if(state[0] == 5) {
HIFISetHK("normal",true);
HIFICloseObs();
}
}
}
//Chopper health check: step#2
procedure Chopper_FT2_COP_proc_ops {
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
//Chopper health check: needs to start in open loop
double lo_freq = 0.0;
double chopper_voltage = 0.0;
Init_MSA_ops("0","OPEN",lo_freq,chopper_voltage,"ON",prime_or_redundant);
Chopper_openloop_scan_block_ops(prime_or_redundant);
//
//Close the loop
string chop_startup_prime_red = "chop_startup_cold_prime";
if(prime_or_redundant == "Red") {
chop_startup_prime_red = "chop_startup_cold_red";
}
{double,string}[] result = ConfigurationReader("name_chopper",[chop_startup_prime_red],"0",0.0);
Init_MSA_ops("0","CLOSE",lo_freq,result[0]{0},"ON",prime_or_redundant);
}
// 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;
}
//HIFI-COP-2.1-DipCal1
obs HifiEng_Diplexer_calibration_vs_D2_COP {
string band = "3" in ["3","4","6","7"]; // HIFI mixer band
}{
// pre_timing
{int,int} pre_timing = Eng_pre_timing(band + "a","both");
int initlength = pre_timing{0};
int closelength = pre_timing{1};
int mainduration = duration(Diplexer_calibration_vs_D2_proc_fm(band));
// 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();
HIFILCUChecksumAndSetHK(band + "a","fast",true);
}
if(state[0] == 3) {
// Test execution
Diplexer_calibration_vs_D2_proc_fm(band);
}
if(state[0] == 5) {
HIFILCUChecksumAndSetHKCloseObs(band + "b",false,"normal",true);
HIFICloseObs();
}
}
}
// HRS attenuator tuning, block
// Both polarizations are treated
block HRS_tune_fast_block_fm HIFI 3991 {
string band = "1a"; // HIFI band
int hrstunedelay = 2; //delay used to perform the HRS tuning
}{
//Start_block();
//First //de-select HRS HK
Hifi_HIFI_Housekeeping_on("1_pkt_per_s","ON","ON","ON","ON","OFF","OFF");
//Now tune attenuators: it sets the HRS to ultra_wide
Hifi_HIFI_Tune_HRS($BBID);
delay(hrstunedelay);
//
//Switch on HRS HK polling back
Hifi_HIFI_Housekeeping_on("1_pkt_per_s","ON","ON","ON","ON","ON","ON");
}
//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);
//
}
//Force boot, block
block HIFI_force_boot_block_ops HIFI 7600 {
int partition_ID = 0; //0 if forceboot_default. Partition ID in case it should be used.
}{
if(partition_ID == 0) {
mois_comment("ICU booted using default partition.");
Hifi_HIFI_force_bootdefault();
} else {
mois_comment("ICU booted using partition # " + partition_ID);
Hifi_HIFI_force_bootpartition(partition_ID);
}
mois_tmcheck("Verify HIFI HK telemetry packets (3,25,1025) - HIFI_PERIODIC_HK - are arriving every 4 seconds.");
//mois_tmcheck("Verify that no (5,4) telemetry packet has been received from HIFI.");
//Increase delay - SPR-1354
delay(5);
//This is not standard practice but here we can only start
//to stamp HKs with obsid/bbid pair after ICU is up and running
//StartBlock_ops(); //removed for moc_cus_1.3 because the next block asks for this already
}
//Startblock
procedure Start_block_no_hk_request {
}{
//These are ILT-EGSE commands, not ruled by the 2TC/sec.
//HifiIltEgse_FPU_set_BB_ID($BBID);
//HifiIltEgse_PDU_set_BB_ID($BBID);
//SpireIltEgse_QCC_SETBBID($BBID);
//delay(1);
Hifi_HIFI_Set_OBS_ID($BBID,$OBSID);
//Hifi_HIFI_non_periodic_hk_FCU();
delay(1);
}
// LCU switch-off, procedure
procedure LCU_switch_off_proc_fm {
}{
//
//Automatic failure mode clearance.
//Should take <0.5s so time included in the switch-off delay
Hifi_HIFI_HL_Normal($BBID);
//
{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_fm("1a","stby");
}
//HIFI LO tuning only for M1 and M2 investigation in 7b, block
//Target current is read from look-up table
block LCU_config_w_paramscan_block_fm HIFI 3018 {
string band = "1a" in ["1a","4b"]; // HIFI band
double lo_freq = 551.0; //LO frequency
string parm = "G1" in ["G1","G2","D1","D2","M1","M2"]; //Parameter to scan: G1,G2,D1,D2,M1,M2
double param_value = -6.0; //Value of parameter to set
}{
//Clear potential failure mode
Set_LO_Nominal_proc_fm();
//
{double,string}[] result = ConfigurationReader("name_confpolar4lotune",[band],band,lo_freq);
string mixer_polarization = result[0]{1};
//Get target mixer current
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_configlcu,["plevel_v","m1_v","m2_v","m3_v","d2_step","gate1_v"],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];
//For 6b, we need a freq-dependent G1V
if(band == "6b") {
gate1_v = result[5]{0};
}
//
double gate2_v = cresult[1];
double drain1_v = cresult[2];
//
result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq);
double drain2_v = result[0]{0};
//
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};
//
//Update parameter to scan
if(parm == "G1") {
gate1_v = param_value;
}
if(parm == "G2") {
gate2_v = param_value;
}
if(parm == "D1") {
drain1_v = param_value;
}
if(parm == "D2") {
drain2_v = param_value;
}
if(parm == "M1") {
m1_v = param_value;
}
if(parm == "M2") {
m2_v = param_value;
}
//
//If something else than Vd2 is scanned, a proper tuning is needed
if(parm != "D2") {
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};
//
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;
//
double drain2_bluemax = Get_BLUE_LIMIT_D2_proc_fm(band,lo_freq);
double tune_range = 0.1;
result = ConfigurationReader(name_configlcutune,["drain2_v"],band,lo_freq);
double middle_d2 = result[0]{0};
double drain2_v_start = min(middle_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);
drain2_v = drain2_v_start;
//
}
result = ConfigurationReader("name_delays",["config_lo_delay"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//Send command
if(band == "1a") {
if(lo_freq < 535.5) {
error("at this frequency you cannot control M1V");
//Hifi_HIFI_Conf_safe_LCU_ch1a($BBID,freq_nx,lsu_main,lsu_offset,
// d2_step,drain2_v,curlim2_v,macro_checksum);
} else {
Hifi_HIFI_Conf_nom_LCU_ch1a($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v,curlim2,macro_checksum);
}
//Command delay
delay(config_lo_delay);
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
if(band == "4b") {
Hifi_HIFI_Conf_nom_LCU_ch4b($BBID,freq_nx,lsu_main,lsu_offset,d2_step,plevel_v,m1_v,m2_v,gate1_v,gate2_v,drain1_v,curlim1,drain2_v,curlim2,macro_checksum);
//Command delay
delay(config_lo_delay);
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//If Vd2 not scanned, do the vector scan
if(parm != "D2") {
if(band == "1a") {
//Band 1a
if(lo_freq < 535.5) {
error("At this frequency you cannot control M1V");
//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);
} else {
Hifi_HIFI_Load_vector_nom_1a($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 == "4b") {
//Band 4b
Hifi_HIFI_Load_vector_nom_4b($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);
}
//
delay(1);
//
//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
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
}
// LCU configuration into DISSIPATIVE mode, procedure
procedure LCU_config_dissipative_w_D2_proc_aot {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
}{
//
//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_configlo = "name_configlo_b";
name_configlcu = "name_configlcu_b";
name_confindex = "name_confindex_b";
}
//
double[] cresult = CalibrationReader("name_lcu_dissipative",["lo_freq"],band,0.0);
double lo_freq = cresult[0];
//
cresult = CalibrationReader("name_lcu_safe_values",["pl_c","m1_v","m2_v","m3_v","g1_v","g2_v","d1_v","d2_v"],band,lo_freq);
double plevel_v = cresult[0];
double m1_v = cresult[1];
double m2_v = cresult[2];
double m3_v = cresult[3];
double gate1_v = cresult[4];
double gate2_v = cresult[5];
double drain1_v = cresult[6];
double drain2_v = cresult[7];
//
cresult = CalibrationReader("name_lcu_dissipative",["d2_step","nx"],band,lo_freq);
int d2_step = iround(cresult[0]);
int freq_nx = ifloor(cresult[1]);
//
//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
{double,string}[] 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"],band,lo_freq);
int config_lo_delay = iround(result[0]{0});
//
//Send command: expect that we have already switched to NOMINAL
HIFI_Configure_LCU_dissipative_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);
//
// Put heaters explicitly to 4 V
mois_step("Set heaters to normal mode value");
HL_heater_block_aot(band,"nominal");
//
//Configure to Dissipative
Set_LO_Dissipative_block_aot();
}
//Chopper health check test#2 during open loop, mode
mode HifiManCmd_Chopper_openloop_scan_health_check {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
mois_tmcheck("The instrument can be in Standby I, Standby II or Primary mode in open loop context for this test");
//It is done after chopper has been switched on in open loop
mois_spacon("Check that procedure HIFI_Chopper_openloop_set_health_check has been performed previously and analysed as PASS");
if(prime_or_redundant == "Prime") {
mois_tmcheck("The instrument must have been switched on with the PRIME side");
} else {
mois_tmcheck("The instrument must have been switched on with the REDUNDANT side");
}
mois_tmcheck("Check that parameter HF_DPR_CHLOOP_S is set to OPEN");
mois_tmcheck("Check that parameter HF_DPR_CHSINE_S is set to ON");
//
mois_comment("Performing part two of HIFI internal chopper health check");
StartMode_block_ops();
//
mois_step("Perform chopper scan in open loop");
Chopper_openloop_scan_block_ops(prime_or_redundant);
//
StopMode_block_mois();
mois_spacon("Write down the OBS_ID corresponding to this mode and communicate it to the HIFI ICC");
}
// HRS partial configuration with choice of central freq for hr sub-band, block
// Configures the LO and attenuators
block FSW_Response_time_HRSConfig_block_fm HIFI 3689 {
string band = "1a"; // HIFI band
string[] hrs_mode = ["hr","hr"]; //HRS resolution code
double hr_central_freq = 5.0; //IF freq of HRS hr sub-band in GHz
}{
//Start_block();
// 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_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 = [hr_central_freq,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_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 = [hr_central_freq,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 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);
}
// 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.");
}
}
// FPU Standby with chopper switched on. HBB is also ON per default, procedure
procedure Band0_chopper_on_proc_fm {
string band = "0"; // HIFI band
string chop_loop = "CLOSE"; // Chopper Loop status
}{
//Start_block();
//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,0.0);
int band_nb = iround(result_d[0]{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,0.0);
//
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_on"],band,0.0);
//
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};
//
result_d = ConfigurationReader("name_confilfpu",["bias_standby_h","diplexer_standby_h","bias_standby_v","diplexer_standby_v","diplex_h_ctrl_mode","diplex_v_ctrl_mode","chop_cold"],band,0.0);
//
double bias_H = result_d[0]{0};
double diplex_H = result_d[1]{0};
double bias_V = result_d[2]{0};
double diplex_V = result_d[3]{0};
int diplex_h_ctrl_mode = iround(result_d[4]{0});
int diplex_v_ctrl_mode = iround(result_d[5]{0});
//
//Retrieve magnets Magnet are so far at maximum value. Now set to nominal
double magnetcurrent_H = result_d[1]{0};
double magnetcurrent_V = result_d[4]{0};
//
if(band != "6a" && band != "6b" && band != "7a" && band != "7b") {
result_d = ConfigurationReader("name_confilfpu",["magnet_standby_h","magnet_standby_v"],band,0.0);
magnetcurrent_H = result_d[0]{0};
magnetcurrent_V = result_d[1]{0};
}
//
result_d = ConfigurationReader("name_chopper",["chop_startup_cold"],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.
//chopper = Check_Chopper_Prime_Redundant(chopper);
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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,0.0);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
}
//////////////////////////////////////////////////////////////////
// HRS complete configuration with maximum attenuation, procedure
// Both polarizations are treated
procedure HRS_standby_proc_ops {
string band = "0"; // 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_ops(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_proc_ops(band,hrs_mode);
//
//Check attenuator values
mois_tmcheck("Check that parameters HRH_1U_ATT, HRH_1L_ATT, HRH_2U_ATT, HRH_2L_ATT, HRH_3U_ATT, HRH_3L_ATT, HRH_4U_ATT and HRH_4L_ATT are set to 15.5");
mois_tmcheck("Check that parameters HRV_1U_ATT, HRV_1L_ATT, HRV_2U_ATT, HRV_2L_ATT, HRV_3U_ATT, HRV_3L_ATT, HRV_4U_ATT and HRV_4L_ATT are set to 15.5");
//Check LO locks and values
mois_tmcheck("Check that parameters HRH_LOCK_LO1_S, HRH_LOCK_LO2_S, HRH_LOCK_LO3_S, HRH_LOCK_LO4_S, HRH_LOCK_LO5_S, HRH_LOCK_LO6_S, and HRH_LOCK_LO7_S are all Locked");
mois_tmcheck("Check that parameters HRV_LOCK_LO1_S, HRV_LOCK_LO2_S, HRV_LOCK_LO3_S, HRV_LOCK_LO4_S, HRV_LOCK_LO5_S, HRV_LOCK_LO6_S, and HRV_LOCK_LO7_S are all Locked");
Check_HRS_LO_proc_ops([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]);
}
//Procedure to store currently tuned frequency, procedure
//Only applicable to non-FSW obs.
procedure HIFI_HL_store_tm_only_proc_fm {
}{
Hifi_HIFI_HL_store_tm($BBID);
delay(1);
}
//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
}
//Set to rescue from switched off
mode HifiManCmd_HIFI_SwitchedOff_to_Rescue {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
string prime_or_redundant = "Prime" in ["Prime","Red"]; //Prime or Red
}{
Mode_status_check_switched_off();
mois_comment("Switching to rescue mode");
mois_step("Power ON the ICU - start up the BSW");
string icu_subsys = "ICU_Prime";
if(prime_or_redundant == "Red") {
icu_subsys = "ICU_Red";
}
PDU_switch_on_block_ops(icu_subsys);
Mode_status_check_rescue("normal");
}
// 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","halfbeam","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;
double[] hrs1aux = [0.0];
double[] hrs2aux = [0.0];
double[] sortarr = [0.0];
// 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 - get step sizes
stepsize = flyCrossStep * degreesPerArcsec;
if(flyNyquistSel) {
double[] s = CalibrationReader("beam",["nyquist"],band,av_lo_freq);
stepsize = s[0];
}
if(stepsize <= 0.0) {
s = CalibrationReader("beam",["halfbeam"],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)};
nlines = imax(iceil(flyY * degreesPerArcmin / stepsize),1);
// extend map by rim for OTF
if(modeName == "fly" || modeName == "fs-raster" || modeName == "load-raster") {
npoints = imax(iceil((flyX * degreesPerArcmin + 1.1 * stepsize) / stepsize),2);
} else {
npoints = imax(iceil(flyX * degreesPerArcmin / stepsize),2);
}
// 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" || crossStepSize == "halfbeam") {
s = CalibrationReader("beam",[crossStepSize],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]];
int[] hrsUseBands = [1,1,2,2];
} else {
hrsUseMap = [[true,false,false,false],[true,true,false,false],[true,true,true,true],[true,true,true,true]];
hrsUseBands = [1,2,4,4];
}
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
hrs1aux = [mix - fe_hrs1_h_0,mix - fe_hrs2_h_0,mix - fe_hrs3_h_0,mix - fe_hrs4_h_0];
hrs2aux = [mix - fe_hrs1_v_0,mix - fe_hrs2_v_0,mix - fe_hrs3_v_0,mix - fe_hrs4_v_0];
} else {
hrs1aux = [fe_hrs1_h_0,fe_hrs2_h_0,fe_hrs3_h_0,fe_hrs4_h_0];
hrs2aux = [fe_hrs1_v_0,fe_hrs2_v_0,fe_hrs3_v_0,fe_hrs4_v_0];
}
// Order HRS subbands to assign USB frequencies to first subbands
sortarr = DSort(hrs1aux,hrsUseBands[hrs1{1}]);
for(int j1 = 0 .. 3) {
hrs1{2}[j1] = sortarr[j1] * factorMHzPerGHz;
}
sortarr = DSort(hrs2aux,hrsUseBands[hrs2{1}]);
for(int j2 = 0 .. 3) {
hrs2{2}[j2] = sortarr[j2] * 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;
}
//Diplexer FSW investigation: phase-block
procedure Dip_FSW_B_phase {
string band = "3a" in ["3a","3b","4a","4b","6a","6b","7a","7b"]; // HIFI band
bool retune = true; //whether the diplexer is adjusted between frequencies or not
double lo_freq2 = 810.0;
double lo_freq_ref = 810.0;
int[] res = [4,1];
string backend = "both";
string polarization = "H" in ["H","V"]; //The polarization on which the test is done
bool modulate = true; //whether we change FSW register and DPACT
}{
//Integrate at FSW1
if(modulate) {
Activate_FSW_register_block_fm("FSW2");
if(retune) {
Set_Single_Diplexer_current_block_fm(band,lo_freq2,polarization);
} else {
Set_Single_Diplexer_current_block_fm(band,lo_freq_ref,polarization);
}
} else {
//Hifi_HIFI_noop();
}
Spectro_total_power_AOTLike_block_fm(band,res,backend);
//Add 2sec for investigation of SPR-2404
delay(2);
}
//////////////////////////////////////////////////////////////////////
// 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);
// Combined sideband scaling
double[] gssb = InterpolateGssb(band,reffreq);
double avgainfac = 0.5 / gssb[0] + 0.5 / gssb[1];
double rescalefac = gssb[1] * avgainfac;
// 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} * gssb[0] * multiplier;
noisevalues{1} = noisevalues{1} * gssb[0] * 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 decnoise_lores = noisevalues{0} / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]);
double decnoise_hires = noisevalues{1} / sqrt(gssb[0] * gssb[0] + gssb[1] * gssb[1]);
double indnoise_lores = noisevalues{2} * rescalefac;
double indnoise_hires = noisevalues{3} * rescalefac;
} else {
// Get single sideband noise equivalent
decnoise_lores = noisevalues{0} * avgainfac;
decnoise_hires = noisevalues{1} * avgainfac;
indnoise_lores = noisevalues{2} * rescalefac;
indnoise_hires = noisevalues{3} * rescalefac;
}
// Return noise values and the maximum ratio of drift to radiometric noise
return {decnoise_lores,decnoise_hires,indnoise_lores,indnoise_hires,noisevalues{4}};
}
//Switch off upconverter, block
//It assumes that mixer and chopper are also to be switched off
block Upconverter_switch_off_block_fm HIFI 3645 {
}{
Start_block();
Hifi_HIFI_Configure_FCU_Power($BBID,"OFF","OFF","OFF","OFF","OFF");
delay(1);
}
// LCU3b configuration into SAFE mode, procedure
procedure LCU3b_config_safe_proc_fm {
string band = "3b"; // HIFI band
double lo_freq = 900.0 in [852.0,953.0]; //LO frequency
}{
error("This module is obsolete: use LCU_config_nominal_proc_fm instead");
}
// 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];
}
// Magnet current scan, slow, procedure
// IF power as function of magnet current
procedure Magnet_scan_slow_proc {
string band = "1a"; // HIFI band //Setting file
double magnet_current_min_h = -10.0; //minimum magnet current H
double magnet_current_max_h = 15.0; //maximum magnet current H
double magnet_current_min_v = -10.0; //minimum magnet current V
double magnet_current_max_v = 15.0; //maximum magnet current V
int n_steps = 100; //number of steps
string[] hrs_mode = ["wb1","wb1"]; //HRS resolution code: hr,mr,lr,wb1,wb2,wb3
int integ_time = 4; //Total integration time in sec.: at least 2sec !
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
double lo_freq = 522.0; //LO frequency
int tune_target_magnet = 40 in [10,85]; //Target WBS illumination percentage during magnet tuning
double shapiro_bias = 1.8; //Shapiro Mixer bias, same used for both polarization
}{
//
//WBS calibration
//Configure backends to max. attenuation for magnet scan
if(backend == "wbs" || backend == "both" || backend == "wbsFast" || backend == "wbsFast2") {
WBS_calib_fm(band);
}
//
//Configure spectrometers integration
Configure_Spectrometer_proc_fm(band,integ_time,hrs_mode,backend);
//
Magnet_scan_slow_fm(band,magnet_current_min_h,magnet_current_max_h,magnet_current_min_v,magnet_current_max_v,n_steps,integ_time,lo_freq,backend,tune_target_magnet,shapiro_bias);
//Back to nominal values
{double,string}[] result = ConfigurationReader("name_confilfpu",["magnet_current_max_h","magnet_current_max_v"],band,0.0);
//First set magnet to maximum to avoid hysteresis
double magnetcurrent_max_h = result[0]{0};
double magnetcurrent_max_v = result[1]{0};
Set_Magnet_current_block_fm(magnetcurrent_max_h,magnetcurrent_max_v);
//
//Nominal values
result = ConfigurationReader("name_confilmix",["norm_magn_h","norm_magn_v","norm_bias_h","norm_bias_v"],band,lo_freq);
Set_Magnet_current_block_fm(result[0]{0},result[1]{0});
//Also set bias voltages back to nominal values
Mixerbias_block_fm(result[2]{0},result[3]{0});
}
////////////////////////////////////
// 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 Engineering - DBS Raster Map halfThrow fastChop",{data_time,0,n_int_on,n_switch_on,0,0,n_pointsperscan,0,n_cycles,load_interval});
ChopMessages(true,data_time,n_int_on);
RasterSizeMessages(lineDistance,stepsize,nlines,npoints,false);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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}};
}
//
// Diplexer scan very fast, block.
// Mixer current as function of diplexer current.
// Uses the new OBS TC allowing much faster scan.
block Scan_diplexer_block_fm HIFI 3254 {
string band = "3a"; // HIFI band
double diplexer_current_min_h = -2.24; //minimum diplexer current H
double diplexer_current_min_v = -2.24; //minimum diplexer current V
double diplexer_current_step = 0.1; //maximum diplexer current V
int n_steps = 100; //number of steps
double stepTime = 0.1; //Step time in seconds
}{
//Start_block();
//double stepTime = 0.07; //Should be in a config file eventually
//Check how many TCs need to be sent
int max_step = 61;
int nloop = iceil(double(n_steps) / double(max_step));
//Compute number of step for last interation
int last_n_steps = n_steps - (nloop - 1) * max_step;
int dipscan_delay = 0;
//
//Preset to first value and wait 1sec (for possible overshoot)
Set_Diplexer_current_proc_fm(diplexer_current_min_h,diplexer_current_min_v);
//Send command
for(int i = 1 .. nloop) {
n_steps = max_step;
diplexer_current_min_h = diplexer_current_min_h + double((i - 1) * max_step) * diplexer_current_step;
diplexer_current_min_v = diplexer_current_min_v + double((i - 1) * max_step) * diplexer_current_step;
if(i == nloop) {
n_steps = last_n_steps;
}
Hifi_HIFI_scan_diplexer($BBID,n_steps,stepTime,diplexer_current_min_h,diplexer_current_min_v,diplexer_current_step);
//Compute delay
dipscan_delay = iceil(1.0 + double(n_steps) * (stepTime + 0.03));
delay(dipscan_delay + 1);
}
}
//Magnet tune fine, procedure
procedure Magnet_tune_fine {
string band = "1a"; // HIFI band
int integ_time = 4; //Integration time
double lo_freq = 522.0; //LO frequency
string backend = "both" in ["both","hrs","wbs","hrsFast","wbsFast","wbsFast2"]; //Backend in use: both, hrs, wbs, hrsFast or wbsFast
}{
Magnet_scan_fine_fm(band,integ_time,lo_freq,backend);
}
///////////////////////////////////////////////////////////////////
// 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};
}
/////////////////////////////////////////////////////////
// WBS configuration with maximum attenuation, block
// Lasers set up as in config file
block WBS_config_max_att_block_fm HIFI 3638 {
string band = "1a"; // HIFI band
}{
//Start_block();
//H-Polarization
//
{double,string}[] result_d = ConfigurationReader("name_configwbs",["hwh_laser1_s","hwh_laser2_s","hwh_heater","hwh_latchup_s"],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 = 7;
int hwh_att_band3 = 7;
int hwh_att_band2 = 7;
int hwh_att_band1 = 7;
int hwh_att_in = 15;
//
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);
//V-Polarization
//Get configuration parameters
//
result_d = ConfigurationReader("name_configwbs",["hwv_laser1_s","hwv_laser2_s","hwv_heater","hwv_latchup_s"],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 = 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);
//
//Wait delay to allow all setting to be configured
delay(wbs_config_delay);
}
//General LO configuration command
// Uses SFT approach with safe call to 3b BUT combined TM page dump
block HIFI_Configure_LCU_block_spur HIFI 3978 {
string band = "1a" in ["1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
double lo_freq = 500.0; //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);
//
//Start_block();
//
//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);
//
//Store settings into available register
//HIFI_HL_store_tm_proc_fm();
//
//Additional read of TM pages
LCU_Read_TM_pages_proc_fm();
}
//Force boot, procedure: NOT LONGER USED, USE BLOCK INSTEAD
procedure HIFI_force_boot_proc {
int partition_ID = 0; //0 if forceboot_default. Partition ID in case it should be used.
}{
if(partition_ID == 0) {
Hifi_HIFI_force_bootdefault();
} else {
Hifi_HIFI_force_bootpartition(partition_ID);
}
//Increase delay - SPR-1354
delay(5);
}
////////////////////////////////////////////////////////////////////////////
// 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();
}
}
}
/////////////////////////////////////////////////////////////////
// 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};
}
// Initialisation of FPU, block with only H-MSA in use
// It is only for cold context
block Init_MSA_H_fm HIFI 3207 {
string band = "1a";
string chop_loop = "CLOSE";
double lo_freq = 522.0; //LO frequency
}{
Start_block();
//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"],"0",0.0);
//
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_on"],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};
//
//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,0.0);
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.
//chopper = Check_Chopper_Prime_Redundant(chopper);
chopper = Check_Chopper_Range(chopper);
//
//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_fm(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,lo_freq);
int config_fpu_delay = iround(result_d[0]{0});
delay(config_fpu_delay);
//
//In case of band 6 or 7, bias have been set to 4mV. Now set to nominal
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
{double,string}[] result = ConfigurationReader("name_confilmix",["norm_bias_h","norm_bias_v"],band,lo_freq);
Mixerbias(result[0]{0},result[1]{0});
}
//
//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);
}
//
Hifi_HIFI_non_periodic_hk_FCU();
}
/////////////////////////////////////////////////////////////////
// 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};
}
////////////////////////////////////
// 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 - DBS Raster Map fastChop",{data_time,0,n_switch_on,n_int_on,0,0,n_pointsperscan,0,n_cycles,load_interval});
ChopMessages(true,data_time,n_int_on);
RasterSizeMessages(lineDistance,stepsize,nlines,npoints,false);
// 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);
// Final message to check for both polarizations
PolarizationMessage(hrs1{0},hrs2{0},wbs1{0},wbs2{0});
// 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};
}
//Contingency for LOU temp FDIR modification
mode HifiManCmd_LOU_FDIR_enable {
string warning_message = "WARNING: THIS MODE IS NOT DESIGNED TO BE SCHEDULED - ONLY HERE FOR MANUAL COMMANDING !!"; //READ THIS CAREFULLY!
}{
mois_comment("Procedure to enable and modify FDIR limits for LOU operational temperatures");
//StartMode_block_ops();
//
mois_spacon("Verify that HM122190 (HI_auto_LOU_S) is OFF. If it is ON check with ICC whether this is fine to proceed");
mois_step("Set new FDIR limits");
Set_LO_FDIR_temperatures_block_mois();
//
mois_spacon("Verify that HM122190 (HI_auto_LOU_S) is ON");
StopMode_block_mois();
// -> to issue last obsd/bbid
}
//Chopper rotation block. It takes into account
//overshoot risk and performs the rotation in
//2 steps if the targetted positions are either of the end stops
block Chopper_Rotation_block_fm HIFI 3646 {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string chop_current_position = "chop_hot_ang"; //Current chopper position
string chop_target_position = "chop_cold_ang"; //Targetted chopper position
}{
Start_block();
//Retrieve angles of corresponding positions
{double,string}[] result_d = ConfigurationReader("name_chopper",[chop_current_position,chop_target_position,"chop_endstopright_ang","chop_endstopleft_ang","overshoot"],band,0.0);
double chop_current_angle = result_d[0]{0};
double chop_target_angle = result_d[1]{0};
double chop_endstopright_angle = result_d[2]{0};
double chop_endstopleft_angle = result_d[3]{0};
double overshoot = result_d[4]{0};
string chop_target_name = result_d[1]{1};
string chop_current_name = result_d[0]{1};
int step = 1;
//
//Check whether the rotation may reach either of the end stops, i.e.
//go beyond either the HBB or M3_left
///// We suppose here overshoot to be 0, so the 2 steps only occur when targetting
///// the end stops strictly.
overshoot = 0.0;
double total_angle = abs(chop_target_angle - chop_current_angle) * (1.0 + overshoot);
//
//The endstop that one may hit depends on the rotating direction
//Case were endstop is the left one
double angle_to_endstop = abs(chop_endstopleft_angle - chop_current_angle);
if(chop_target_angle > chop_current_angle) {
//then end stop is the right one
angle_to_endstop = abs(chop_endstopright_angle - chop_current_angle);
}
//debug_print(total_angle);
//debug_print(angle_to_endstop);
if(total_angle >= angle_to_endstop) {
message("Chopper expected to hit the endstop. Rotation done in two steps");
step = 2;
}
//If we have two steps necessary, the middle position between current and
//targetted position is used.
result_d = ConfigurationReader("name_confilfpu",[chop_target_name,chop_current_name],band,0.0);
double chop = result_d[0]{0};
double chop_intermediate = (result_d[0]{0} + result_d[1]{0}) / 2.0;
//
chop = Check_Chopper_Prime_Redundant(chop);
if(step == 1) {
HIFI_CPR_Chopper_Rot_proc_fm(chop);
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent voltage
delay(1);
}
if(step == 2) {
chop_intermediate = Check_Chopper_Prime_Redundant(chop_intermediate);
HIFI_CPR_Chopper_Rot_proc_fm(chop_intermediate);
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent voltage
delay(1);
HIFI_CPR_Chopper_Rot_proc_fm(chop);
Hifi_HIFI_non_periodic_hk_FCU();
//To get sent voltage
delay(1);
}
}
/////////////////////////////////////////////////////////////////
// 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};
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Testmodes for Functional test of WBS FM
//
// DT - 21/09/04: first draft for QM
// DT - 04/11/04: added new modes
// 19/07/05: Updated for FM
// 09/12/05: Updated after WBS FM delivery.
// Laser2 is the default laser for ILT.
// 22/01/07: Laser1 is the default laser for FM ILT.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Modes: see fm_testmodes.cus
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Associated blocks
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Special COMB FT for WBS, procedure
// Follows procedure requested after COMB problem discovered on WBS-V
procedure FT_COMB_proc_fm {
string band = "1a" in ["0","1a","1b","2a","2b","3a","3b","4a","4b","5a","5b","6a","6b","7a","7b"]; // HIFI band
string laser_H = "Laser1" in ["Laser1","Laser2"]; //WBS-H laser to be set ON
string laser_V = "Laser1" in ["Laser1","Laser2"]; //WBS-V laser to be set ON
}{
//Allow fast HK readout
HKrate(1.0);
//
int integ_time = 2;
//Total integration time in sec.
int[] res = Configure_Spectrometer_proc_fm(band,integ_time,["wb1","wb1"],"wbs");
//Scan all attenuators with COMB ON
FT_WBS_att_overall_COMB_fm(band,integ_time,laser_H,laser_V,"wbs");
FT_WBS_att_individual_COMB_fm(band,integ_time,laser_H,laser_V,"wbs");
//
//Att. at 7/7/7/7/7
WBS_config_w_laser_and_att_block_fm(band,laser_H,laser_V,[7,7,7,7,7],[7,7,7,7,7]);
//Spectra with COMB ON - various integration times
res = Configure_Spectrometer_proc_fm(band,2,["wb1","wb1"],"wbs");
Spectro_total_power_block_fm(band,res,"wbs");
res = Configure_Spectrometer_proc_fm(band,10,["wb1","wb1"],"wbs");
Spectro_total_power_block_fm(band,res,"wbs");
res = Configure_Spectrometer_proc_fm(band,20,["wb1","wb1"],"wbs");
Spectro_total_power_block_fm(band,res,"wbs");
res = Configure_Spectrometer_proc_fm(band,30,["wb1","wb1"],"wbs");
Spectro_total_power_block_fm(band,res,"wbs");
//Switch off zero and comb after the above
Switch_zero_comb_block_fm("OFF");
//Back to slow HK readout
HKrate(0.25);
}
/////////////////////////////////////////////////////////////////
// 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;
}
//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,true);
//
//Magnet tuning: use either HRS or WBS, not for bands 1,2,6,7 (SCR-2380)
if(band == "3a" || band == "3b" || band == "4a" || band == "4b" || band == "5a" || band == "5b") {
// 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
// Extra stabilization only for HEB bands
if(band == "6a" || band == "6b" || band == "7a" || band == "7b") {
LO_tuning_block_aot(band,lo_freq_2 / 1000.0,lo_freq_setting,tuningbackend,false,true,true,true);
} else {
LO_tuning_block_aot(band,lo_freq_2 / 1000.0,lo_freq_setting,tuningbackend,false,true,true,false);
}
//
}
// Last message of an observing mode - check for polarizations, close message body
procedure PolarizationMessage {
bool hrs1used = true;
bool hrs2used = true;
bool wbs1used = true;
bool wbs2used = true;
}{
// Check whether both polarizations are used in at least one spectrometer system
if(hrs1used && hrs2used || wbs1used && wbs2used) {
message("