예제 #1
0
void dsp::LoadToFold::prepare ()
{
  assert (fold.size() > 0);

  prepare_fold ();

  const Pulsar::Predictor* predictor = 0;
  if (fold[0]->has_folding_predictor())
    predictor = fold[0]->get_folding_predictor();

  if (phased_filterbank)
    phased_filterbank->bin_divider.set_predictor( predictor );

  const Pulsar::Parameters* parameters = 0;
  if (fold[0]->has_pulsar_ephemeris())
    parameters = fold[0]->get_pulsar_ephemeris();

  double dm = 0.0;

  if (config->dispersion_measure)
  {
    dm = config->dispersion_measure;
    if (Operation::verbose)
      cerr << "LoadToFold::prepare config DM=" << dm << endl;
  }
  else if (parameters)
  {
    dm = get_dispersion_measure (parameters);
    if (Operation::verbose)
      cerr << "LoadToFold::prepare ephem DM=" << dm << endl;
  }

  if (config->coherent_dedispersion)
  {
    if (dm == 0.0)
      throw Error (InvalidState, "LoadToFold::prepare",
                   "coherent dedispersion enabled, but DM unknown");

    if (kernel)
      kernel->set_dispersion_measure (dm);
  }

  manager->get_info()->set_dispersion_measure( dm );

  // --repeat must reset the dm when the input is re-opened
  config->dispersion_measure = dm;

  /*
    In the case of unpacking two-bit data, set the corresponding
    parameters.  This is done in prepare because we really ought
    to set nsample to the largest number of samples smaller than the
    dispersion smearing, and in general the DM is known only after the
    ephemeris is prepared by Fold.
  */

  dsp::ExcisionUnpacker* excision;
  excision = dynamic_cast<dsp::ExcisionUnpacker*> ( manager->get_unpacker() );

  if (excision)
  {
    if ( config->excision_nsample )
      excision -> set_ndat_per_weight ( config->excision_nsample );
  
    if ( config->excision_threshold > 0 )
      excision -> set_threshold ( config->excision_threshold );
    
    if ( config->excision_cutoff >= 0 )
      excision -> set_cutoff_sigma ( config->excision_cutoff );
  }

  MJD fold_reference_epoch = parse_epoch (config->reference_epoch);

  for (unsigned ifold=0; ifold < fold.size(); ifold++)
  {
    if (ifold < path.size())
    {
      Reference::To<Extensions> extensions = new Extensions;
      extensions->add_extension( path[ifold] );
    
      for (unsigned iop=0; iop < operations.size(); iop++)
	operations[iop]->add_extensions (extensions);
    
      fold[ifold]->get_output()->set_extensions (extensions);
    }

    fold[ifold]->set_reference_epoch (fold_reference_epoch);
  }

  SingleThread::prepare ();

  // for now ...

  minimum_samples = 0;
  unsigned block_overlap = 0;

  bool report_vitals = thread_id==0 && config->report_vitals;

  if (kernel && report_vitals)
    cerr << "dspsr: dedispersion filter length=" << kernel->get_ndat ()
         << " (minimum=" << kernel->get_minimum_ndat () << ")" 
         << " complex samples" << endl;

  if (filterbank)
  {
    minimum_samples = filterbank->get_minimum_samples ();
    if (report_vitals)
    {
      cerr << "dspsr: " << config->filterbank.get_nchan() << " channel ";

      if (config->coherent_dedispersion &&
	  config->filterbank.get_convolve_when() == Filterbank::Config::During)
	cerr << "dedispersing ";
      else if (filterbank->get_freq_res() > 1)
        cerr << "by " << filterbank->get_freq_res() << " back ";

      cerr << "filterbank requires " << minimum_samples << " samples" << endl;
    }

    if (!config->input_buffering)
    {
      block_overlap = filterbank->get_minimum_samples_lost ();
      if (Operation::verbose)
        cerr << "filterbank loses " << block_overlap << " samples" << endl;
    }
  }

  unsigned filterbank_resolution = minimum_samples - block_overlap;

  if (convolution)
  {
    const Observation* info = manager->get_info();
    unsigned fb_factor = convolution->get_input()->get_nchan() * 2;
    fb_factor /= info->get_nchan() * info->get_ndim();

    minimum_samples = convolution->get_minimum_samples () * fb_factor;
    if (report_vitals)
      cerr << "dspsr: convolution requires at least "
           << minimum_samples << " samples" << endl;

    if (!config->input_buffering)
    {
      block_overlap = convolution->get_minimum_samples_lost () * fb_factor;
      if (Operation::verbose)
        cerr << "convolution loses " << block_overlap << " samples" << endl;

      manager->set_filterbank_resolution (filterbank_resolution);
    }
  }

  uint64_t block_size = ( minimum_samples - block_overlap )
    * config->get_times_minimum_ndat() + block_overlap;

  // set the block size to at least minimum_samples
  manager->set_maximum_RAM( config->get_maximum_RAM() );
  manager->set_minimum_RAM( config->get_minimum_RAM() );
  manager->set_copies( config->get_nbuffers() );

  manager->set_overlap( block_overlap );

  uint64_t ram = manager->set_block_size( block_size );

#if HAVE_CFITSIO
#if HAVE_fits
  // if PSRFITS input, set block to exact size of FITS row
  // this is needed to keep in sync with the callback
  if (manager->get_info()->get_machine() == "FITS")
  {
    FITSFile* tmp = dynamic_cast<FITSFile*> (manager->get_input());
    uint64_t block_size;

    if (!tmp)
    {
      MultiFile* mfile = dynamic_cast<MultiFile*> (manager->get_input());
      if (mfile)
      {
        block_size = mfile->get_block_size();
        tmp = dynamic_cast<FITSFile*> ( mfile->get_loader() );
      }
    }
    else
      block_size = tmp->get_block_size();
    if (tmp)
    {
      unsigned samples_per_row = tmp->get_samples_in_row();
      uint64_t current_bytes = manager->set_block_size (samples_per_row);
      uint64_t new_max_ram = current_bytes / block_size * samples_per_row;
      if (new_max_ram > config->get_maximum_RAM ())
        throw Error (InvalidState, "LoadToFold::prepare", 
            "Maximum RAM smaller than PSRFITS row.");
      manager->set_maximum_RAM (new_max_ram);
      manager->set_block_size (samples_per_row);
    }
    else
      cerr << "dspsr: WARNING have FITS input but cannot set block size properly." << endl;
  }
#endif
#endif

  if (report_vitals)
  {
    double megabyte = 1024*1024;
    cerr << "dspsr: blocksize=" << manager->get_input()->get_block_size()
         << " samples or " << double(ram)/megabyte << " MB" << endl;
  }
}
예제 #2
0
파일: pam.C 프로젝트: lbaehren/lofarsoft
int main (int argc, char *argv[]) try {
  
    bool verbose = false;
    char* metafile = 0;
 
    string ulpath;

    bool save = false;
    string ext;
  
    bool tscr = false;
    int tscr_fac = 0;

    bool fscr = false;
    int fscr_fac = 0;

    bool bscr = false;
    int bscr_fac = 0;

    bool newdm = false;
    double dm = 0.0;

    bool scattered_power_correction = false;

    bool defaraday = false;

    bool newrm = false;
    double rm = 0.0;

    bool reset_weights = false;
    float new_weight = 1.0;

    float smear_dc = 0.0;

    bool rotate = false;
    double rphase = 0.0;

    bool dedisperse = false;
    bool dededisperse = false;

    bool pscr = false;

    bool invint = false;

    bool stokesify = false;
    bool unstokesify = false;

    bool flipsb = false;
    bool flip_freq = false;
    double flip_freq_mhz = 0.0;

    Pulsar::Parameters* new_eph = 0;

    string command = "pam";

    char* archive_class = 0;

    int new_nchn = 0;
    int new_nsub = 0;
    int new_nbin = 0;

    float tsub = 0.0;

    bool circ = false;
    bool lin = false;

    unsigned ronsub = 0;
    bool cbppo = false;
    bool cbpao = false;
    bool cblpo = false;
    bool cblao = false;

    int subint_extract_start = -1;
    int subint_extract_end = -1;

    bool new_cfreq = false;
    double new_fr = 0.0;
    Signal::Source new_type = Signal::Unknown;
    string instrument;
    bool reverse_freqs = false;
    string site;
    string name;
    float mult = -1.0;
    double new_folding_period = -1.0;

    bool update_dm_from_eph = false;
    double aux_rm = 0.0;

    Reference::To<Pulsar::IntegrationOrder> myio;
    Reference::To<Pulsar::Receiver> install_receiver;

    Pulsar::ReflectStokes reflections;

    int c = 0;

    const int TYPE = 1208;
    const int INST = 1209;
    const int REVERSE_FREQS = 1210;
    const int SITE = 1211;
    const int NAME = 1212;
    const int DD   = 1213;
    const int RR   = 1214;
    const int SPC  = 1215;
    const int RM   = 1216;
    const int MULT = 1218;
    const int PERIOD=1219;
    const int SS   = 1220;
    const int FLIP = 1221;
    const int UPDATE_DM = 1222;
    const int AUX_RM = 1223;

    while (1) {

      int options_index = 0;

      static struct option long_options[] = {
	{"setnchn",    1, 0, 200},
	{"setnsub",    1, 0, 201},
	{"setnbin",    1, 0, 202},
	{"binphsperi", 1, 0, 203},
	{"binphsasc",  1, 0, 204},
	{"binlngperi", 1, 0, 205},
	{"binlngasc",  1, 0, 206},
	{"receiver",   1, 0, 207},
	{"settsub",    1, 0, 208},
	{"type",       1, 0, TYPE},
	{"inst",       1, 0, INST},
	{"reverse_freqs",no_argument,0,REVERSE_FREQS},
	{"flip",       1 ,0, FLIP},
	{"site",       1, 0, SITE},
	{"name",       1, 0, NAME},
	{"DD",         no_argument,      0,DD},
	{"RR",         no_argument,      0,RR},
	{"RM",         required_argument,0,RM},
	{"spc",        no_argument,      0,SPC},
	{"mult",       required_argument,0,MULT},
	{"period",     required_argument,0,PERIOD},
	{"SS",         no_argument,      0,SS},
	{"update_dm",   no_argument,      0,UPDATE_DM},
	{"aux_rm",    required_argument,0,AUX_RM},
	{0, 0, 0, 0}
      };

      c = getopt_long(argc, argv, "hqvViM:mn:a:e:E:TFpIt:f:b:d:o:s:r:u:w:DSBLCx:R:",
		      long_options, &options_index);

      if (c == -1)
	break;

      switch (c) {
      case 'h':
	usage();
	return (0);
	break;
      case 'q':
	Pulsar::Archive::set_verbosity(0);
	break;
      case 'v':
	verbose = true;
	Pulsar::Archive::set_verbosity(2);
	break;
      case 'V':
	verbose = true;
	Pulsar::Archive::set_verbosity(3);
	break;
      case 'i':
	cout << "$Id: pam.C,v 1.101 2010/10/05 23:59:50 jonathan_khoo Exp $" << endl;
	return 0;
      case 'm':
	save = true;
	break;
      case 'M':
        metafile = optarg;
        break;
      case 'L':
	lin = true;
	break;
      case 'C':
	circ = true;
	break;
      case 'a':
	archive_class = optarg;
	break;
      case 'e':
	ext = optarg;
	if( !ext.empty() )
	  save = true;
	break;
      case 'E':

	try {
	  new_eph = factory<Pulsar::Parameters> (optarg);
	}
	catch (Error& error) {
	  cerr << "Could not load new ephemeris from " << optarg << endl;
	  return -1;
	}

	command += " -E";
	break;
      case 'T':
	tscr = true;
	command += " -T";
	break;
      case 'F':
	fscr = true;
	command += " -F";
	break;
      case 'p':
	pscr = true;
	command += " -p";
	break;
      case 'I':
	invint = true;
	pscr = false;
	command += " -I";
	break;
      case 'f':
	fscr = true;
	if (sscanf(optarg, "%d", &fscr_fac) != 1) {
	  cout << "That is not a valid fscrunch factor" << endl;
	  return -1;
	}
	command += " -f ";
	command += optarg;
	break;
	
      case 'n':

	reflections.add_reflection( optarg[0] );

	command += " -n ";
	command += optarg;
	break;

      case 'o':
	new_cfreq = true;
	if (sscanf(optarg, "%lf", &new_fr) != 1) {
	  cout << "That is not a valid centre frequency" << endl;
	  return -1;
	}
	command += " -o ";
	command += optarg;
	break;
      case 't':
	tscr = true;
	if (sscanf(optarg, "%d", &tscr_fac) != 1) {
	  cout << "That is not a valid tscrunch factor" << endl;
	  return -1;
	}
	command += " -t ";
	command += optarg;
	break;
      case 'b':
	bscr = true;
	if (sscanf(optarg, "%d", &bscr_fac) != 1) {
	  cout << "That is not a valid bscrunch factor" << endl;
	  return -1;
	}
	if (bscr_fac <= 0) {
	  cout << "That is not a valid bscrunch factor" << endl;
	  return -1;
	}
	command += " -b ";
	command += optarg;
	break;
      case 'd':
	newdm = true;
	if (sscanf(optarg, "%lf", &dm) != 1) {
	  cout << "That is not a valid dispersion measure" << endl;
	  return -1;
	}
	command += " -d ";
	command += optarg;
	break;
      case 'D':
	dedisperse = true;
	command += " -D ";
	break;
      case 'R':
	if (sscanf(optarg, "%lf", &rm) != 1) {
	  cout << "That is not a valid rotation measure" << endl;
	  return -1;
	}
	newrm = true;
	defaraday = true;
	command += " -R ";
	command += optarg;
	break;
      case 's':
	if (sscanf(optarg, "%f", &smear_dc) != 1) {
	  cout << "That is not a valid smearing duty cycle" << endl;
	  return -1;
	}
	command += " -s ";
	command += optarg;
	break;
      case 'r':
	rotate = true;
	if (sscanf(optarg, "%lf", &rphase) != 1) {
	  cout << "That is not a valid rotation phase" << endl;
	  return -1;
	}
	if (rphase <= -1.0 || rphase >= 1.0) {
	  cout << "That is not a valid rotation phase" << endl;
	  return -1;
	}
	command += " -r ";
	command += optarg;
	break;
      case 'u':
	ulpath = optarg;
	if( !ulpath.empty() )
	{
	  save = true;
	  if (ulpath.substr(ulpath.length()-1,1) != "/")
	    ulpath += "/";
	}
	break;
      case 'w':
	reset_weights = true;
	if (sscanf(optarg, "%f", &new_weight) != 1) {
	  cout << "That is not a valid weight" << endl;
	  return -1;
	}
	command += " -w ";
	command += optarg;
	break;
      case 'S':
	stokesify = true;
	break;
      case SS:
        unstokesify = true;
        break;
      case 'B':
	flipsb = true;
	break;
      case 'x' :
	if (sscanf(optarg, "%d %d", 
		   &subint_extract_start, &subint_extract_end) !=2 ) {
	  cout << "That is not a valid subint range" << endl;
	  return -1;
	}
	subint_extract_end++;
	break;
      case 200:
	fscr = true;
	if (sscanf(optarg, "%d", &new_nchn) != 1) {
	  cout << "That is not a valid number of channels" << endl;
	  return -1;
	}
	if (new_nchn <= 0) {
	  cout << "That is not a valid number of channels" << endl;
	  return -1;
	}
	command += " --setnchn ";
	command += optarg;
	break;
      case 201:
	tscr = true;
	if (sscanf(optarg, "%d", &new_nsub) != 1) {
	  cout << "That is not a valid number of subints" << endl;
	  return -1;
	}
	if (new_nsub <= 0) {
	  cout << "That is not a valid number of subints" << endl;
	  return -1;
	}
	command += " --setnsub ";
	command += optarg;
	break;
      case 202:
	bscr = true;
	if (sscanf(optarg, "%d", &new_nbin) != 1) {
	  cout << "That is not a valid number of bins" << endl;
	  return -1;
	}
	if (new_nbin <= 0) {
	  cout << "That is not a valid number of bins" << endl;
	  return -1;
	}
	command += " --setnbin ";
	command += optarg;
	break;
      case 203: {
	if (cbpao || cblpo || cblao) {
	  cerr << "You can only specify one re-ordering scheme!"
	       << endl;
	  return -1;
	}
	if (sscanf(optarg, "%ud", &ronsub) != 1) {
	  cerr << "Invalid nsub given" << endl;
	  return -1;
	}
	cbppo = true;
	break;
      } 
      case 204: {
	if (cbppo || cblpo || cblao) {
	  cerr << "You can only specify one re-ordering scheme!"
	       << endl;
	  return -1;
	}
	if (sscanf(optarg, "%ud", &ronsub) != 1) {
	  cerr << "Invalid nsub given" << endl;
	  return -1;
	}
	cbpao = true;
	break;
      }      
      case 205: {
	if (cblao || cbppo || cbpao) {
	  cerr << "You can only specify one re-ordering scheme!"
	       << endl;
	  return -1;
	}
	if (sscanf(optarg, "%ud", &ronsub) != 1) {
	  cerr << "Invalid nsub given" << endl;
	  return -1;
	}
	cblpo = true;
	break;
      } 
      case 206: {
	if (cblpo || cbppo || cbpao) {
	  cerr << "You can only specify one re-ordering scheme!"
	       << endl;
	  return -1;
	}
	if (sscanf(optarg, "%ud", &ronsub) != 1) {
	  cerr << "Invalid nsub given" << endl;
	  return -1;
	}
	cblao = true;
	break;
      }

      case 207: try {
	install_receiver = Pulsar::Receiver::load (optarg);
	break;
      }
      catch (Error& error) {
	cerr << "pam: Error loading Receiver from " << optarg << endl
	     << error.get_message() << endl;
	return -1;
      }

      case 208: {
	if (sscanf(optarg, "%f", &tsub) != 1) {
	  cerr << "Invalid tsub given" << endl;
	  return -1;
	}
	tscr = true;
	break;
      }

      case TYPE:
	{
	  string s = optarg;
	  if(s=="Pulsar")     new_type = Signal::Pulsar;
	  else if(s=="PolnCal")    new_type = Signal::PolnCal;
	  else if(s=="FluxCalOn")  new_type = Signal::FluxCalOn;
	  else if(s=="FluxCalOff") new_type = Signal::FluxCalOff;
	  else if(s=="Calibrator") new_type = Signal::Calibrator;
	  else{
	    fprintf(stderr,"Unrecognised argument to --type: '%s'\n",optarg);
	    exit(-1);
	  }
	  command += " --type " + s;
	}
	break;

      case INST: instrument = optarg; break;

      case REVERSE_FREQS: reverse_freqs = true; break;

      case SITE: site = optarg; break;

      case NAME: name = optarg; break;

      case DD: dededisperse = true; break;

      case RM:
        aux_rm = fromstring<double>(optarg);
        newrm = true;
        command += " --RM ";
        command += optarg;
        break;

      case SPC: scattered_power_correction = true; break;
	
      case MULT: mult = atof(optarg); break;

      case PERIOD: new_folding_period = fromstring<double>(optarg); break;

      case FLIP: flip_freq = true; flip_freq_mhz = atof(optarg); break;

      case UPDATE_DM: update_dm_from_eph = true; break;

      case AUX_RM:
        aux_rm = fromstring<double>(optarg);
        command += " --aux_rm ";
        command += optarg;
        break;

      default:
	cout << "Unrecognised option" << endl;
      }
    }

   if (verbose)
     cerr << "pam: parsing filenames" << endl;
 
   vector <string> filenames;

    if (metafile)
      stringfload (&filenames, metafile);
    else
      for (int ai=optind; ai<argc; ai++)
        dirglob (&filenames, argv[ai]);
 
    if (filenames.empty())
    {
      cerr << "pam: no filenames were specified" << endl;
      exit(-1);
    } 
  
    Reference::To<Pulsar::Archive> arch;

    if (!save)
    {
      cout << "Changes will not be saved. Use -m, -u or -e to write results to disk"
	   << endl;
    }

    if (stokesify && unstokesify)
    {
      cerr << "pam: Both -S and --SS options were given.  Poln state will not be changed!" << endl;
      stokesify = false;
      unstokesify = false;
    }

    int flip_option_count=0;
    if (flipsb) flip_option_count++;
    if (flip_freq) flip_option_count++;
    if (reverse_freqs) flip_option_count++;
    if (flip_option_count > 1) {
      cerr << "pam: More than one band-flip option was given, exiting." << endl;
      exit(-1);
    }

    for (unsigned i = 0; i < filenames.size(); i++) try
    {
      if (verbose)
	cerr << "Loading " << filenames[i] << endl;
      
      arch = Pulsar::Archive::load(filenames[i]);

      if( mult > 0.0 ){
	for( unsigned isub=0; isub<arch->get_nsubint();isub++)
	  for( unsigned ichan=0; ichan<arch->get_nchan();ichan++)
	    for( unsigned ipol=0; ipol<arch->get_npol();ipol++)
	      arch->get_Profile(isub,ipol,ichan)->scale( mult );
      }

      if( new_folding_period > 0.0 ){
	Pulsar::counter_drift( arch, new_folding_period, 0.0);
	for( unsigned isub=0; isub<arch->get_nsubint();isub++)
	  arch->get_Integration(isub)->set_folding_period( new_folding_period );
      }

      if (install_receiver) {
	if (verbose)
	  cerr << "pam: Installing receiver: " << install_receiver->get_name()
	       << " in archive" << endl;

	arch->add_extension (install_receiver);
      }

      if (lin || circ) {
	Pulsar::Receiver* receiver = arch->get<Pulsar::Receiver>();

	if (!receiver)
	  cerr << "No Receiver Extension in " << filenames[i] << endl;
	else {
	  if (lin) {
	    receiver->set_basis (Signal::Linear);
	    cout << "Feed basis set to Linear" << endl;
	  }

	  if (circ) {
	    receiver->set_basis (Signal::Circular);
	    cout << "Feed basis set to Circular" << endl;
	  }
	}
      }

      reflections.transform( arch );

      if (new_cfreq)
      {
	double nc = arch->get_nchan();
	double bw = arch->get_bandwidth();
	double cw = bw / nc;

	double fr = new_fr - (bw / 2.0) + (cw / 2.0);
	
	for (unsigned i = 0; i < arch->get_nsubint(); i++) {
	  for (unsigned j = 0; j < arch->get_nchan(); j++) {
	    arch->get_Integration(i)->set_centre_frequency(j,(fr + (j*cw)));
	  }
	}
	
	arch->set_centre_frequency(new_fr);
      }

      if( new_type != Signal::Unknown )
	arch->set_type( new_type );

      if( instrument != string() ){
	Pulsar::Backend* b = arch->get<Pulsar::Backend>();
	if( !b )
	  fprintf(stderr,"Could not change instrument name- archive does not have Backend extension\n");
	else
	  b->set_name(instrument);
      }

      if( site != string() )
	arch->set_telescope( site );

      if( name != string() )
	arch->set_source( name );

      if (new_eph) try
      {
        arch->set_ephemeris(new_eph);

        if (update_dm_from_eph) {
          update_dm(arch);
        }
      }
      catch (Error& error)
      {
	cerr << "Error while installing new ephemeris: " 
	     << error.get_message() << endl;
        continue;
      }

      if (flipsb) {
	for (unsigned i = 0; i < arch->get_nsubint(); i++) {
	  vector<double> labels;
	  labels.resize(arch->get_nchan());
	  for (unsigned j = 0; j < arch->get_nchan(); j++) {
	    labels[j] = arch->get_Integration(i)->get_centre_frequency(j);
	  }
	  for (unsigned j = 0; j < arch->get_nchan(); j++) {
	    double new_frequency = labels[labels.size()-1-j];
	    arch->get_Integration(i)->set_centre_frequency(j,new_frequency);
	  }
	}
	arch->set_bandwidth(-1.0 * arch->get_bandwidth());
      }

      if (flip_freq) {
        for (unsigned isub = 0; isub < arch->get_nsubint(); isub++) {
          Reference::To<Pulsar::Integration> 
            subint = arch->get_Integration(isub);
          for (unsigned ichan = 0; ichan < arch->get_nchan(); ichan++) {
            double new_freq = flip_freq_mhz 
              - (subint->get_centre_frequency(ichan) - flip_freq_mhz);
            subint->set_centre_frequency(ichan, new_freq);
          }
        }
        arch->set_bandwidth(-1.0 * arch->get_bandwidth());
      }

      if( reverse_freqs ) {
	// Of course it would be nice to do this with pointers.... but oh well I guess copying will have to do HSK 27/8/04

	unsigned nchan = arch->get_nchan();

	for( unsigned isub=0; isub<arch->get_nsubint(); isub++){
	  for( unsigned ipol =0; ipol<arch->get_npol(); ipol++){
	    for( unsigned ichan=0; ichan<nchan/2; ichan++){
	      Reference::To<Pulsar::Profile> lo = arch->get_Profile(isub,ipol,ichan);	      
	      Reference::To<Pulsar::Profile> tmp = lo->clone();

	      Reference::To<Pulsar::Profile> hi = arch->get_Profile(isub,ipol,nchan-1-ichan);

	      lo->operator=(*hi);
	      hi->operator=(*tmp);
	    }
	  }
	}
	arch->set_bandwidth( -1.0 * arch->get_bandwidth() );
      }

      if (reset_weights) {
	arch->uniform_weight(new_weight);
	if (verbose)
	  cout << "All profile weights set to " << new_weight << endl;
      }
      
      if (rotate)
	arch->rotate_phase (rphase);

      if (scattered_power_correction) {

	Pulsar::ScatteredPowerCorrection spc;
	if (arch->get_state() == Signal::Stokes)
	  arch->convert_state(Signal::Coherence);

	spc.correct (arch);

      }

      if (newdm)
      {
	arch->set_dispersion_measure(dm);
	if (verbose)
	  cout << "Archive dispersion measure set to " << dm << endl;

	if (arch->get_dedispersed())
        {
	  arch->dedisperse();

	  if (verbose)
	    cout << "Archive re-dedipsersed" << endl;
        }
      }

      if (dedisperse)
      {
	arch->dedisperse();
	if (verbose)
	  cout << "Archive dedipsersed" << endl;
      }

      if (dededisperse)
      {
	Pulsar::Dispersion correction;
	correction.revert (arch);
      }

      if (stokesify) {
	if (arch->get_npol() != 4)
	  throw Error(InvalidState, "Convert to Stokes",
		      "Not enough polarisation information");
	arch->convert_state(Signal::Stokes);
	if (verbose)
	  cout << "Archive converted to Stokes parameters" << endl;
      }

      if (unstokesify) {
	if (arch->get_npol() != 4)
	  throw Error(InvalidState, "Convert to coherence",
		      "Not enough polarisation information");
	arch->convert_state(Signal::Coherence);
	if (verbose)
	  cout << "Archive converted to coherence parameters" << endl;
      }

      if (cbppo) {
	myio = new Pulsar::PeriastronOrder();
	arch->add_extension(myio);
	myio->organise(arch, ronsub);
      }
      
      if (cbpao) {
	myio = new Pulsar::BinaryPhaseOrder();
	arch->add_extension(myio);
	myio->organise(arch, ronsub);
      }
      
      if (cblpo) {
	myio = new Pulsar::BinLngPeriOrder();
	arch->add_extension(myio);
	myio->organise(arch, ronsub);
      }
      
      if (cblao) {
	myio = new Pulsar::BinLngAscOrder();
	arch->add_extension(myio);
	myio->organise(arch, ronsub);
      }
      
      if( subint_extract_start >= 0 && subint_extract_end >= 0 ) {
	vector<unsigned> subints;
	unsigned isub = subint_extract_start;

	while ( isub<arch->get_nsubint() && isub<unsigned(subint_extract_end) ) {
	  subints.push_back( isub );
	  isub++;
	}

	Reference::To<Pulsar::Archive> extracted( arch->extract(subints) );
	extracted->set_filename( arch->get_filename() );

	arch = extracted;
      }

      if (tscr) {
	if (tsub > 0.0) {
	  unsigned factor = 
	    unsigned (tsub / arch->get_Integration(0)->get_duration());
	  if (factor == 0) {
	    cerr << "Warning: subints already too long" << endl;
	  }
	  else {
	    arch->tscrunch(factor);
	  }
	  if (verbose)
	    cout << arch->get_filename() << " tscrunched by a factor of " 
		 << factor << endl;
	}
	else if (new_nsub > 0) {
	  arch->tscrunch_to_nsub(new_nsub);
	  if (verbose)
	    cout << arch->get_filename() << " tscrunched to " 
		 << new_nsub << " subints" << endl;
	}
	else if (tscr_fac > 0) {
	  arch->tscrunch(tscr_fac);
	  if (verbose)
	    cout << arch->get_filename() << " tscrunched by a factor of " 
		 << tscr_fac << endl;
	}
	else {
	  arch->tscrunch();
	  if (verbose)
	    cout << arch->get_filename() << " tscrunched" << endl;
	}
      }
      
      if (pscr) {
	arch->pscrunch();
	if (verbose)
	  cout << arch->get_filename() << " pscrunched" << endl;
      } 

      if (invint) {
	arch->invint();
	if (verbose)
	  cout << arch->get_filename() << " invinted" << endl;
      }

      if (newrm) {
	arch->set_rotation_measure (rm);
	if (verbose)
	  cout << arch->get_filename() << " RM set to " << rm << endl;
      }

      if (defaraday) {
	arch->defaraday();
	if (verbose)
	  cout << arch->get_filename() << " defaradayed" <<endl;
      }

      if (aux_rm)
      {
	if (verbose)
	  cout << "pam: correct auxiliary Faraday rotation; iono RM="
	       << aux_rm << endl;
	correct_auxiliary_rm (arch, aux_rm);
      }

      if (fscr) {
	if (new_nchn > 0) {
	  arch->fscrunch_to_nchan(new_nchn);
	  if (verbose)
	    cout << arch->get_filename() << " fscrunched to " 
		 << new_nchn << " channels" << endl;
	}
	else if (fscr_fac > 0) {
	  arch->fscrunch(fscr_fac);
	  if (verbose)
	    cout << arch->get_filename() << " fscrunched by a factor of " 
		 << fscr_fac << endl;
	}
	else {
	  arch->fscrunch();
	  if (verbose)
	    cout << arch->get_filename() << " fscrunched" << endl;
	}
      }

      if (bscr) {
	if (new_nbin > 0) {
	  arch->bscrunch_to_nbin(new_nbin);
	  if (verbose)
	    cout << arch->get_filename() << " bscrunched to " 
		 << new_nbin << " bins" << endl;
	}
	else {
	  arch->bscrunch(bscr_fac);
	  if (verbose)
	    cout << arch->get_filename() << " bscrunched by a factor of " 
		 << bscr_fac << endl;
	}
      }     

      if (smear_dc) {
	for (unsigned i = 0; i < arch->get_nsubint(); i++) {
	  for (unsigned j = 0; j < arch->get_npol(); j++) {
	    for (unsigned k = 0; k < arch->get_nchan(); k++) {
	      smear (arch->get_Profile(i,j,k), smear_dc);
	    }
	  }
	}
      }
      
      if (save) {

	if (archive_class)  {

	  // unload an archive of the specified class
	  Reference::To<Pulsar::Archive> output;
	  output = Pulsar::Archive::new_Archive (archive_class);
	  output -> copy (*arch);
	  output -> set_filename ( arch->get_filename() );

	  arch = output;

	}


	// See if the archive contains a history that should be updated:
	
	Pulsar::ProcHistory* fitsext = arch->get<Pulsar::ProcHistory>();
	
	if (fitsext) {
	  
	  if (command.length() > 80) {
	    cout << "WARNING: ProcHistory command string truncated to 80 chars" 
		 << endl;
	    fitsext->set_command_str(command.substr(0, 80));
	  }
	  else {
	    fitsext->set_command_str(command);
	  }
	  
	}
	
	string out_filename = arch->get_filename();
	
	if( !ext.empty() )
	  out_filename = replace_extension( out_filename, ext );
	
	if( !ulpath.empty() )
	  out_filename = ulpath + basename(out_filename);
	
	arch->unload( out_filename );
	cout << out_filename << " written to disk" << endl;
      }
    }  
    catch (Error& error) {
      cerr << error << endl;
    } 
  
    return 0;

}
catch(Error& er) 
{
  cerr << er << endl;
  return -1;
}
catch (string& error)
{
  cerr << "exception thrown: " << error << endl;
  return -1;
}
catch (bad_alloc& ba)
{
  cerr << "Caught a bad_alloc: '" << ba.what() << "'" << endl ;
  return -1;
}
catch (exception& e)
{
  cerr << "caught an exception of type '" 
				 << typeid(e).name() << "'" << endl; 
  return -1;
}
catch(...)
{
  fprintf(stderr,"Unknown exception caught\n");
  return -1;
}