//__________________________________________________________________________
// co_ZenAzCorrection(unsigned char TiD)
//__________________________________________________________________________
bool co_ZenAzCorrection(telescope_id TID,
                        double *zen, double *az, double rot_angle) {
    static receiver_config ReceiverConfig;
    if (ReceiverConfig.s4_id != TID) {
        char buf[256];
        sprintf(buf,"where s4_id=%d",TID);
        ReceiverConfig.fetch(buf);
    }
    return co_ZenAzCorrection(ReceiverConfig, zen, az, rot_angle);
}
int main() {
   if (!sql_database("sah2b@sci_master_tcp")) exit(1);
   std::cout << "<receiver_array>\n";
   std::cout << xml_indent() << "<row_count>" <<  input.count() << "</row_count>\n" ;
   if (input.open_query()) {
     while (input.get_next()) {
       std::cout << input.print_xml();
     }
   }
   std::cout << "</receiver_array>\n";
}
int main() {
   int i,j;
   if (!sql_database("sah2b@sci_master_tcp")) exit(1);
   if (!getenv("S4_RECEIVER_CONFIG"))
	putenv("S4_RECEIVER_CONFIG="S4_RECEIVER_CONFIG_FILE);

   for (i=0;i<3;i++)  {
     memset(&input,0,sizeof(input));
     s4cfg_GetReceiverConfig(i, &input);
     output.s4_id=input.ReceiverID;
     strncpy(output.name,input.ReceiverName,255);
     output.name[254]=0;
     output.beam_width=input.BeamWidth;
     output.center_freq=input.CenterFreq;
     output.latitude=input.Latitude;
     output.longitude=input.Longitude;
     output.elevation=input.Elevation;
     output.diameter=input.Diameter;
     output.az_orientation=input.AzOrientation;
     output.zen_corr_coeff.clear();
     output.az_corr_coeff.clear();
     for (j=0;j<13;j++) {
       output.zen_corr_coeff.push_back(input.ZenCorrCoeff[j]);
       output.az_corr_coeff.push_back(input.AzCorrCoeff[j]);
     }
     db_change("sah2b@sci_master_tcp");
     output.id=0;
     if (output.insert()) {
       std::cout << "inserted row (id=" << output.id << ")" << std::endl;
     } else {
       std::cout << "insert failed, sql_error_code =" << sql_error_code() << " sql_last_error_code =" << sql_last_error_code() << std::endl;
     }
   }
}       
bool co_ZenAzCorrection(receiver_config &ReceiverConfig,
                        double *zen, double *az, double rot_angle) {
    double CosAz, SinAz, SinZen, Cos2Az, Sin2Az, Cos3Az, Sin3Az, Cos6Az, Sin6Az, SinZen2,
           Cos3Imb, Sin3Imb, AzRadians, ZenRadians, ZenCorrection, AzCorrection;

    if ((ReceiverConfig.center_freq == 0) && !ReceiverConfig.fetch()) {
        return false;
    }

    if (isnan(ReceiverConfig.array_az_ellipse)) {
        ReceiverConfig.array_az_ellipse=0;
    }
    if (isnan(ReceiverConfig.array_za_ellipse)) {
        ReceiverConfig.array_za_ellipse=0;
    }
    if (isnan(ReceiverConfig.array_angle)) {
        ReceiverConfig.array_angle=0;
    }

#ifdef DEBUG
    static int printed=0;
    int i;
    if (!printed) {
        fprintf(stderr, "%d\n", TiD);
        fprintf(stderr, "ID = %ld  Name = %s  Lat = %lf  Lon = %lf  El = %lf  Dia = %lf  BW = %lf\n",
                ReceiverConfig.s4_id,
                ReceiverConfig.name,
                ReceiverConfig.latitude,
                ReceiverConfig.longitude,
                ReceiverConfig.elevation,
                ReceiverConfig.diameter,
                ReceiverConfig.beam_width);

        for (i=0; i < ReceiverConfig.zen_corr_coeff.size(); i++) {
            fprintf(stderr, "%lf ", ReceiverConfig.zen_corr_coeff[i]);
        }
        fprintf(stderr, "\n");
        for (i=0; i < ReceiverConfig.az_corr_coeff.size(); i++) {
            fprintf(stderr, "%lf ", ReceiverConfig.az_corr_coeff[i]);
        }
        fprintf(stderr, "\n");
        fprintf(stderr, "array_az_ellipse=%lf array_za_ellipse=%lf array_angle=%lf",
                ReceiverConfig.array_az_ellipse,ReceiverConfig.array_za_ellipse,
                ReceiverConfig.array_angle
               );
        printed++;
    }
#endif


// Start of port of AO Phil's IDL routine modeval.pro
    AzRadians  = *az  * D2R;
    ZenRadians = *zen * D2R;

    CosAz  = cos(AzRadians);
    SinAz  = sin(AzRadians);
    Cos2Az = cos(2.0 * AzRadians);
    Sin2Az = sin(2.0 * AzRadians);
    Cos3Az = cos(3.0 * AzRadians);
    Sin3Az = sin(3.0 * AzRadians);
    Cos6Az = cos(6.0 * AzRadians);
    Sin6Az = sin(6.0 * AzRadians);

    SinZen  = sin(ZenRadians);
    SinZen2 = SinZen * SinZen;

    Cos3Imb = sin(ZenRadians - 0.1596997627) * Cos3Az;    // 0.159... = 9.15 deg.  This is related
    Sin3Imb = sin(ZenRadians - 0.1596997627) * Sin3Az;    // to the balance of dome and CH. (via Phil)

    ZenCorrection = ReceiverConfig.zen_corr_coeff[ 0]             +
                    ReceiverConfig.zen_corr_coeff[ 1] * CosAz     +
                    ReceiverConfig.zen_corr_coeff[ 2] * SinAz     +
                    ReceiverConfig.zen_corr_coeff[ 3] * SinZen    +
                    ReceiverConfig.zen_corr_coeff[ 4] * SinZen2   +
                    ReceiverConfig.zen_corr_coeff[ 5] * Cos3Az    +
                    ReceiverConfig.zen_corr_coeff[ 6] * Sin3Az    +
                    ReceiverConfig.zen_corr_coeff[ 7] * Cos3Imb   +
                    ReceiverConfig.zen_corr_coeff[ 8] * Sin3Imb   +
                    ReceiverConfig.zen_corr_coeff[ 9] * Cos2Az    +
                    ReceiverConfig.zen_corr_coeff[10] * Sin2Az    +
                    ReceiverConfig.zen_corr_coeff[11] * Cos6Az    +
                    ReceiverConfig.zen_corr_coeff[12] * Sin6Az;

    AzCorrection  = ReceiverConfig.az_corr_coeff[ 0]                +
                    ReceiverConfig.az_corr_coeff[ 1] * CosAz        +
                    ReceiverConfig.az_corr_coeff[ 2] * SinAz        +
                    ReceiverConfig.az_corr_coeff[ 3] * SinZen       +
                    ReceiverConfig.az_corr_coeff[ 4] * SinZen2      +
                    ReceiverConfig.az_corr_coeff[ 5] * Cos3Az       +
                    ReceiverConfig.az_corr_coeff[ 6] * Sin3Az       +
                    ReceiverConfig.az_corr_coeff[ 7] * Cos3Imb      +
                    ReceiverConfig.az_corr_coeff[ 8] * Sin3Imb      +
                    ReceiverConfig.az_corr_coeff[ 9] * Cos2Az       +
                    ReceiverConfig.az_corr_coeff[10] * Sin2Az       +
                    ReceiverConfig.az_corr_coeff[11] * Cos6Az       +
                    ReceiverConfig.az_corr_coeff[12] * Sin6Az;
// end of port of modeval.pro

// Now correct for the offsets of the beams in the arrays.
// Arrays are distributed on an ellipse.
//  compute the az,za offsets to add to the az, za coordinates
//  these are great circle.
//  1. With zero rotation angle,  the th generated is counter clockwise.
//     The offsets in the azalfaoff.. table were generated from using
//     this orientation of the angle.
//  2. The rotangl of the array is positive clockwise (since that is the
//     way the floor rotates when given a positive number). We use a
//     minus sign since it is opposite of the angle used to generate the
//     offset array above.
//  3. After computing the angle of a beam and projecting it onto the
//     major, minor axis of the ellipse, the values are subtracted
//     from pixel 0 az,za. In other words, the positive direction is the
//     same as we've already used above for our correction, so we can just
//     add it to our correction.

    double posrot=(ReceiverConfig.array_angle-rot_angle)*D2R;
    AzCorrection+=ReceiverConfig.array_az_ellipse*cos(posrot);
    ZenCorrection+=ReceiverConfig.array_za_ellipse*sin(posrot);

    *zen -= ZenCorrection / 3600.0;               // Correction is in arcsec.
    *az  -= (AzCorrection  / 3600.0) / sin(*zen * D2R);   // Correction is in arcsec.

    // Sometimes the azimuth is not where the telescope is
    // pointing, but rather where it is physically positioned.
    *az    += ReceiverConfig.az_orientation;

    if (*zen < 0.0) {                             // Have we corrected zen over
        //  the zenith?
        *zen = 0.0 - *zen;                          // If so, correct zen and
        *az += 180.0;                               //   swing azimuth around to
    }

    *az = wrap(*az, 0L, 360L, TRUE);              // az to 0 - 360 degrees
    return true;
}
int get_configs_old_method(WORKUNIT& boinc_wu, long long seti_wu_id, receiver_config& receiver_cfg, analysis_config& analysis_cfg) {

    workunit 	  s_wu;
    workunit_grp  s_wu_grp;
    int 	  sql_error_code;

    // workunit
    if (s_wu.fetch(seti_wu_id)) {
      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
        "[%s] Obtained science master DB row for wu %lld [%s]\n",
        boinc_wu.name, seti_wu_id, s_wu.name
      );
    } else {
      sql_error_code = sql_last_error_code();
      if (sql_error_code == 100) {
      	log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
        	"[%s] Science master DB row for wuid %lld does not exit.  Marking as assimilated.\n",
        	boinc_wu.name, seti_wu_id
      	);
	return sql_error_code;
      } else {	
      	log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
        	"[%s] Could not obtain science master DB row for wuid %lld. SQLCODE is %d\n",
        	boinc_wu.name, seti_wu_id, sql_error_code
      	);
        return -1;
      }
    }

    // workunit_grp
    if (s_wu_grp.fetch(s_wu.group_info.id)) {
      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
        "[%s] Obtained science master DB row for wugid %ld\n",
        boinc_wu.name, s_wu_grp.id
      );
    } else {
      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
        "[%s] Could not obtain science master DB row for wugid %ld. SQLCODE is %d\n",
        boinc_wu.name, s_wu.group_info.id, sql_last_error_code() 
      );
      return -1;
    }

    // receiver_config - get it if it has changed
    if (receiver_cfg.id != s_wu_grp.receiver_cfg.id) {
    	if (receiver_cfg.fetch(s_wu_grp.receiver_cfg.id)) { 
      		log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
        		"[%s] Obtained science master DB row for receiver table id %ld [%s]\n",
        		boinc_wu.name, receiver_cfg.id, receiver_cfg.name
      		);
    	} else {
      		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
        		"[%s] Could not obtain science master DB row for receiver table id %ld. SQLCODE is %d\n",
        		boinc_wu.name, s_wu_grp.receiver_cfg.id, sql_last_error_code() 
      		);
      	return -1;  
    	}
    }

    // analysis_config - get it if it has changed
    if (analysis_cfg.id != s_wu_grp.analysis_cfg.id) {
     	if (analysis_cfg.fetch(s_wu_grp.analysis_cfg.id)) { 
      		log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
       		 	"[%s] Obtained science master DB row for analysis table id %ld.\n",
       		 	boinc_wu.name, analysis_cfg.id
      		);
    	} else {
      		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
        		"[%s] Could not obtain science master DB row for analysis table id %ld. SQLCODE is %d\n",
        		boinc_wu.name, s_wu_grp.analysis_cfg.id, sql_last_error_code()
      		);
      	return -1;
    	}
    }

    return 0;
}
int get_science_configs(WORKUNIT& boinc_wu, long long seti_wu_id, receiver_config& receiver_cfg, analysis_config& analysis_cfg) {

    int settings_id, retval=0;
    static int first_time=1, current_settings_id=0, current_analysis_config_id=0, current_receiver_config_id=0;
    settings settings;

#if 1
    settings_id = parse_settings_id(boinc_wu);
    if (settings_id) {
        log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
             "[%s] Name string contains  settings id %ld\n",
             boinc_wu.name, settings_id
        );
    } else {
        log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
             "[%s] Name string contains no settings id\n",
             boinc_wu.name
        );
    }
#endif

#if 0
    // temp hack
    if (first_time) {
	    retval = get_configs_old_method(boinc_wu, seti_wu_id, receiver_cfg, analysis_cfg);
	    if (!retval) first_time = 0;
    }
    return (retval);
    // end temp hack
#endif

    // can be removed after all WUs have settings (no settings would then be a fatal error)
    if (!settings_id) {
	    get_configs_old_method(boinc_wu, seti_wu_id, receiver_cfg, analysis_cfg);
        return(0);
    }
    // end can be removed after all WUs have settings

    if (settings_id == current_settings_id) {
	    return (0);
    } else {
        current_settings_id = settings_id;

	    // get settings row
	    if (settings.fetch(settings_id)) {
            log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
                    "[%s] Obtained science master DB row for settings table id %ld\n",
                    boinc_wu.name, settings.id
            );
        } else {
            log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                    "[%s] Could not obtain science master DB row for settings table id %ld. SQLCODE is %d\n",
                    boinc_wu.name, settings_id, sql_last_error_code()
            );
		    return(-1);
	    }

	    // get analysis config row
	    if (settings.analysis_cfg.id != current_analysis_config_id) {
		    if (analysis_cfg.fetch(settings.analysis_cfg.id)) {
                current_analysis_config_id = analysis_cfg.id;
			    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
                       		"[%s] Obtained science master DB row for analysis_config table id %ld\n",
                     		boinc_wu.name, analysis_cfg.id
                );
            } else {
               	log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        	"[%s] Could not obtain science master DB row for analysis_config table id %ld. SQLCODE is %d\n",
                        	boinc_wu.name, settings.analysis_cfg.id, sql_last_error_code()
               	);
			    return(-1);
		    }
        }

	    // get receiver config row 
	    if (settings.receiver_cfg.id != current_receiver_config_id) {
		    if (receiver_cfg.fetch(settings.receiver_cfg.id)) {
                current_receiver_config_id = receiver_cfg.id;
			    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
                       		"[%s] Obtained science master DB row for receiver_config table id %ld\n",
                       		boinc_wu.name, receiver_cfg.id
                );
           	} else {
               	log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                           	"[%s] Could not obtain science master DB row for receiver_config table id %ld. SQLCODE is %d\n",
                        	boinc_wu.name, settings.receiver_cfg.id, sql_last_error_code()
               	);
			    return(-1);
		    }
        }
        
        return(0);

    }
}
int make_wu_headers(tapeheader_t tapeheader[],workunit wuheader[],
                    buffer_pos_t *start_of_wu) {
  int procid=getpid();
  int i,j,startframe=start_of_wu->frame;
  double receiver_freq;
  int bandno;
  SCOPE_STRING *lastpos;
  FILE *tmpfile;
  char tmpstr[256];
  char buf[64];
  static int HaveConfigTable=0;
  static ReceiverConfig_t ReceiverConfig;   
  static receiver_config r;
  static settings s;

  if(!HaveConfigTable) {
    sprintf(buf,"where s4_id=%d",gregorian?AOGREG_1420:AO_1420);
    r.fetch(std::string(buf));
    ReceiverConfig.ReceiverID=r.s4_id;
    strlcpy(ReceiverConfig.ReceiverName,r.name,
           sizeof(ReceiverConfig.ReceiverName));
    ReceiverConfig.Latitude=r.latitude;
    ReceiverConfig.Longitude=r.longitude;
    ReceiverConfig.WLongitude=-r.longitude;
    ReceiverConfig.Elevation=r.elevation;
    ReceiverConfig.Diameter=r.diameter;
    ReceiverConfig.BeamWidth=r.beam_width;
    ReceiverConfig.CenterFreq=r.center_freq;
    ReceiverConfig.AzOrientation=r.az_orientation;
    for (i=0;i<(sizeof(ReceiverConfig.ZenCorrCoeff)/sizeof(ReceiverConfig.ZenCorrCoeff[0]));i++) {
      ReceiverConfig.ZenCorrCoeff[i]=r.zen_corr_coeff[i];
      ReceiverConfig.AzCorrCoeff[i]=r.az_corr_coeff[i];
    }
    HaveConfigTable=1;
  }
  sprintf(buf,"where active=%d",app.id);
  if (!s.fetch(std::string(buf))) {
    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to find active settings for app.id=%d\n",app.id);
    exit(1);
  }
  if (s.receiver_cfg->id != r.id) {
    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Receiver config does not match settings (%d != %d)\n",s.receiver_cfg->id, r.id);
    exit(1);
  }
  s.recorder_cfg->fetch();
  s.splitter_cfg->fetch();
  s.analysis_cfg->fetch();
  if (!strncmp(s.splitter_cfg->data_type,"encoded",
     std::min(static_cast<size_t>(7),sizeof(s.splitter_cfg->data_type)))) {
    noencode=0;
  } else {
      noencode=1;
  }

  workunit_grp wugrp;
  sprintf(wugrp.name,"%s.%ld.%d.%ld.%d",tapeheader[startframe].name,
    procid, 
    (current_record-TAPE_RECORDS_IN_BUFFER)*8+startframe,
    start_of_wu->byte,s.id);
  wugrp.receiver_cfg=r;
  wugrp.recorder_cfg=s.recorder_cfg;
  wugrp.splitter_cfg=s.splitter_cfg;
  wugrp.analysis_cfg=s.analysis_cfg;

  wugrp.data_desc.start_ra=tapeheader[startframe+1].telstr.ra;
  wugrp.data_desc.start_dec=tapeheader[startframe+1].telstr.dec;
  wugrp.data_desc.end_ra=tapeheader[startframe+TAPE_FRAMES_PER_WU].telstr.ra;
  wugrp.data_desc.end_dec=tapeheader[startframe+TAPE_FRAMES_PER_WU].telstr.dec;
  wugrp.data_desc.nsamples=NSAMPLES;
  wugrp.data_desc.true_angle_range=0;
  {
    double sample_rate=tapeheader[startframe].samplerate/NSTRIPS;
    /* startframe+1 contains the first valid RA and Dec */
    TIME st=tapeheader[startframe+1].telstr.st;
    TIME et=tapeheader[startframe+TAPE_FRAMES_PER_WU].telstr.st;
    double diff=(et-st).jd*86400.0;
    for (j=2;j<TAPE_FRAMES_PER_WU;j++) {
      wugrp.data_desc.true_angle_range+=angdist(tapeheader[startframe+j-1].telstr,tapeheader[startframe+j].telstr);
    }
    wugrp.data_desc.true_angle_range*=(double)wugrp.data_desc.nsamples/(double)sample_rate/diff;
    if (wugrp.data_desc.true_angle_range==0) wugrp.data_desc.true_angle_range=1e-10;
  }
  // Calculate the number of unique signals that could be found in a workunit.
  // We will use these numbers to calculate thresholds.
  double numgauss=2.36368e+08/wugrp.data_desc.true_angle_range;
  double numpulse=std::min(4.52067e+10/wugrp.data_desc.true_angle_range,2.00382e+11);
  double numtrip=std::min(3.25215e+12/wugrp.data_desc.true_angle_range,1.44774e+13);

  

  // Calculate a unique key to describe this analysis config.
  long keyuniq=floor(std::min(wugrp.data_desc.true_angle_range*100,1000.0)+0.5)+
    s.analysis_cfg.id*1024.0;
  if ((keyuniq>(13*1024)) ||(keyuniq<12*1024)) {
     log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Invalid keyuniq value!\n");
     log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%d %d %f\n",keyuniq,s.analysis_cfg.id,wugrp.data_desc.true_angle_range);
     exit(1);
  }

  keyuniq*=-1;
  long save_keyuniq=keyuniq;
  s.analysis_cfg=wugrp.analysis_cfg;
  sprintf(tmpstr,"where keyuniq=%d",keyuniq); 
  // Check if we've already done this analysis_config...
  s.analysis_cfg.id=0;
  s.analysis_cfg->fetch(tmpstr);

  if (s.analysis_cfg->id==0) {
    if (keyuniq != save_keyuniq) {
      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"keyuniq value changed!\n");
      exit(1);
    }

    // If not calculate the thresholds based upon the input analysis_config
    // Triplets are distributed exponentially...
    wugrp.analysis_cfg->triplet_thresh+=(log(numtrip)-29.0652);

    // Gaussians are based upon chisqr...
    double p_gauss=lcgf(32.0,wugrp.analysis_cfg->gauss_null_chi_sq_thresh*32.0);
    p_gauss-=(log(numgauss)-19.5358);
    wugrp.analysis_cfg->gauss_null_chi_sq_thresh=invert_lcgf(p_gauss,32,1e-4)*0.03125;

    // Pulses thresholds are log of the probability
    wugrp.analysis_cfg->pulse_thresh+=(log(numpulse)-24.7894);

    wugrp.analysis_cfg->keyuniq=keyuniq;
    wugrp.analysis_cfg->insert();
  } else {
    wugrp.analysis_cfg=s.analysis_cfg;
  }

  strlcpy(wugrp.data_desc.time_recorded,
      short_jd_string(tapeheader[startframe+1].telstr.st.jd),
      sizeof(wugrp.data_desc.time_recorded));
  wugrp.data_desc.time_recorded_jd=tapeheader[startframe+1].telstr.st.jd;

  lastpos=&(tapeheader[startframe].telstr);
  coordinate_t tmpcoord;
  tmpcoord.time=tapeheader[startframe].telstr.st.jd;
  tmpcoord.ra=tapeheader[startframe].telstr.ra;
  tmpcoord.dec=tapeheader[startframe].telstr.dec;
  wugrp.data_desc.coords.push_back(tmpcoord);  

  for (j=1;j<TAPE_FRAMES_PER_WU;j++) {
    if ((tapeheader[startframe+j].telstr.st.jd-lastpos->st.jd) > (1.0/86400.0)) 
    {
      lastpos=&(tapeheader[startframe+j].telstr);
      tmpcoord.time=tapeheader[startframe+j].telstr.st.jd;
      tmpcoord.ra=tapeheader[startframe+j].telstr.ra;
      tmpcoord.dec=tapeheader[startframe+j].telstr.dec;
      wugrp.data_desc.coords.push_back(tmpcoord);  
    }
  }

  wugrp.tape_info->id=0;
  wugrp.tape_info->fetch(std::string("where name=\'")+tapeheader[startframe].name+"\'");
  wugrp.tape_info->start_time=tapeheader[startframe].st.jd;
  wugrp.tape_info->last_block_time=tapeheader[startframe].st.jd;
  wugrp.tape_info->last_block_done=tapeheader[startframe].frameseq;

  if (!nodb) {
    if (wugrp.tape_info.id) {
      if (!(wugrp.tape_info->update())) {
        char buf[1024];
        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%s",sql_error_message());
	exit(1);
      }
    } else {
      strlcpy(wugrp.tape_info->name,tapeheader[startframe].name,sizeof(wugrp.tape_info->name));
      wugrp.tape_info->insert();
    }
  }

  if (!nodb) wugrp.insert();
  
  for (i=0;i<NSTRIPS;i++) {
    bin_data[i].clear();
    wuheader[i].group_info=wugrp;
    sprintf(wuheader[i].name,"%s.%ld.%d.%ld.%d.%d",tapeheader[startframe].name,
       procid, (current_record-TAPE_RECORDS_IN_BUFFER)*8+startframe,
       start_of_wu->byte,s.id,i);
    wuheader[i].subband_desc.sample_rate=tapeheader[startframe].samplerate/NSTRIPS;
 
    receiver_freq=tapeheader[startframe].centerfreq;

    bandno=((i+NSTRIPS/2)%NSTRIPS)-NSTRIPS/2;

    wuheader[i].subband_desc.base=receiver_freq+
	       (double)(bandno)*wuheader[i].subband_desc.sample_rate;
    wuheader[i].subband_desc.center=receiver_freq+wuheader[i].subband_desc.sample_rate*NSTRIPS*((double)IFFT_LEN*bandno/FFT_LEN+(double)IFFT_LEN/(2*FFT_LEN)-1.0/(2*FFT_LEN));
    wuheader[i].subband_desc.number=i;

    if (!nodb ) {
      if (!(wu_database_id[i]=wuheader[i].insert())) {
        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Database error in make_wu_headers()\n");
        exit(EXIT_FAILURE);
      }
    }
	
    sprintf(tmpstr,"./wu_inbox/%s",wuheader[i].name);
    if ((tmpfile=fopen(tmpstr,"w"))) {
      fprintf(tmpfile,"<workunit>\n");
      fprintf(tmpfile,wuheader[i].print_xml().c_str());
      fclose(tmpfile);
    } else {
      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to open file ./wu_inbox/%s, errno=%d\n",wuheader[i].name,errno);
      exit(1);
    }
    bin_data[i].reserve(wuheaders[i].group_info->recorder_cfg->bits_per_sample*
       wuheaders[i].group_info->data_desc.nsamples/8);
  }
  return(1);
}