Index: /trunk/htdocs/ArchiveScruncher.php
===================================================================
--- /trunk/htdocs/ArchiveScruncher.php	(revision 264)
+++ /trunk/htdocs/ArchiveScruncher.php	(revision 264)
@@ -0,0 +1,216 @@
+<?php
+
+
+
+require_once 'File.php';
+require_once 'strutils.php';
+
+
+
+/**
+ * This class represents an archive scrunching algorithm, though
+ * the actual scrunching is performed by executing psrsh. You give
+ * this algorithm
+ * <ul>
+ *  <li> the archive filename </li>
+ *  <li> the directory to save the new scrunched file into </li>
+ *  <li> the scrunching parameters </li>
+ * </ul>
+ **/
+
+class ArchiveScruncher
+{
+  /// PUBLIC
+
+    public function __construct()
+    {
+      $this->pscrunch = false;       // polarization scrunching is either on or off
+      $this->tscrunch = '';          // this is the number of subints to scrunch together
+      $this->fscrunch = '';          // this is the number of channels to scrunch together
+      $this->src_file = new File();  // This is a File class representing the source archive
+      $this->dest_file = new File(); // This is a File class representing the destination archive
+    }
+
+    public function SetSrcFile( File $s_src_file ) { $this->src_file = $s_src_file; }
+    public function SetDestFile( File $s_dest_file ) { $this->dest_file = $s_dest_file; }
+
+    public function PScrunch() { $this->pscrunch = true; }
+    public function TScrunch( $value ) { $this->tscrunch = $value; }
+    public function FScrunch( $value ) { $this->fscrunch = $value; }
+
+    /**
+     * This is the algorithms execute method, determine the destination filename from the
+     * source filename and scrunching parameters, create a script for psrsh to perform the
+     * scrunching and to output the file, then exec psrsh with that script.
+     **/
+
+    public function Execute()
+    {
+      // TODO throw an exception if not scrunching needs to be done
+      //       if( !$this->NeedsScrunching() )
+      //       {
+      //       }
+      
+//       $this->dest_file->SetFilename( $this->CreateScrunchedFilename( $this->src_file->GetFilename(name) ) );
+    
+      $script_file = $this->CreateScrunchingScript();
+    
+      $psrcmd = FIX_LD_LIB . PSRSH_CMD . " $script_file " . $this->src_file->GetFullPath();
+//       echo 'psrcmd is ' . $psrcmd . ' <br> ';
+    
+      $output_array = Array();
+      $retval = '';
+      $last_line = exec( $psrcmd, $output_array, $retval );
+    
+      // TODO throw an exception if we didn't produce an output file
+      if( !file_exists( $this->dest_file->GetFullPath() ) )
+      {
+	echo 'psrsh doesn\'t seem to have created the file we want <br>';
+	echo $this->dest_file->GetFullPath() . '<br>';
+	exit;
+      }
+    }
+
+  /// PRIVATE
+
+    private $src_file;
+    private $dest_file;
+    private $pscrunch;
+    private $tscrunch;
+    private $fscrunch;
+
+
+
+    /**
+     * Return true if atleast one scrunching parameter is set, false otherwise.
+     **/
+
+    private function NeedsScrunching()
+    {
+      return ( $this->pscrunch === false &&
+	  $this->tscrunch == '' &&
+	  $this->fscrunch == '' );
+    }
+
+    /**
+     * Create a temporary file and write into it the instructions for psrsh
+     * to perform to scrunch the file appropriately and write it out to the
+     * target directory.
+     **/
+
+    private function CreateScrunchingScript()
+    {
+      if( $this->fscrunch != '' )
+	$psrscript .= "fscrunch_by $this->fscrunch \n";
+      if( $this->tscrunch != '' )
+	$psrscript .= "tscrunch_by $this->tscrunch \n";
+      if( $this->pscrunch !== false )
+	$psrscript .= "pscrunch \n";
+      $psrscript .= 'unload ' . $this->dest_file->GetFullPath() . "\n";
+
+      $script_filename = tempnam(TEMP_DIR, '');
+
+    // TODO remove this chmod command, its for debugging only
+	exec( 'chmod 666 ' . $script_filename );
+
+      $outfile = fopen( $script_filename, 'r+' );
+      // TODO throw an exception if we can't open the tempfile
+      // if( $outfile === false )
+      fwrite( $outfile, $psrscript );
+      fclose( $outfile );
+
+      return $script_filename;
+    }
+    
+    
+    /**
+     * Call vap to determine the parameters for an archive, nsub,nchan,nbin,npol
+     **/
+    
+    private function DetermineSubintParams( $filename, &$nsub, &$nchan, &$nbin, &$npol )
+    {
+      $cmd = FIX_LD_LIB . VAP_CMD . ' -c nbin,nchan,npol,nsub ' . $filename;
+      $all_lines = Array();
+      $retval = '';
+      
+      $last_line = exec( $cmd, $all_lines, $retval );
+      
+      $vap_response = eatwhite( $last_line );
+      $nbin = strword( $vap_response, 1 );
+      $nchan = strword( $vap_response, 2 );
+      $npol = strword( $vap_response, 3 );
+      $nsub = strword( $vap_response, 4 );
+      
+//       echo "$filename is (nsub,nchan,nbin,npol) ($nsub,$nchan,$nbin,$npol) <br>";
+    } 
+    
+    /**
+     * Use the archive parameters to determine the size of the data in the SUBINT table
+     **/
+    
+    private function DetermineSubintsSize( $nsub, $nchan, $nbin, $npol )
+    {
+      $bytes_per_int = 2;
+      $bytes_per_long = 4;
+      $bytes_per_float = 2;
+      $bytes_per_double = 4;
+      
+      $bytes_per_subint = 
+	  (1 * $bytes_per_long) +
+	  (8 * $bytes_per_double) +
+	  (5 * $bytes_per_float) +
+	  (2 * $nchan * $bytes_per_float) +
+	  (2 * $nchan * $npol * $bytes_per_float) +
+	  ($nbin * $nchan * $npol * $bytes_per_int);
+      
+      return $nsub * $bytes_per_subint;
+    }
+
+    /**
+     * Guess how much disk space the resulting scrunched file will take up
+     **/
+
+    public function GuessScrunchedFileSize()
+    {
+      $filename = $this->src_file->GetFullPath();
+    
+      $original_size = filesize( $filename );
+      if( $original_size === false )
+      {
+	// TODO throw an exception if we can't read the file size
+	echo 'failed to get file size for ' . $filename . ' <br> ';
+	exit;
+      }
+      
+//       echo 'the original file size is ' . $original_size . ' <br> ';
+      
+      $this->DetermineSubintParams( $filename, $nsub, $nchan, $nbin, $npol );
+      
+
+      $original_data_size = $this->DetermineSubintsSize( $nsub, $nchan, $nbin, $npol );
+      
+      $header_size = $original_size - $original_data_size;
+      
+//       echo 'estimating original data size to be ' . $original_data_size . ' <br> ';
+//       echo 'estimating header size to be ' . $header_size . ' <br> ';
+      
+      if( $this->pscrunch )
+	$npol = 1;
+      if( $this->tscrunch != '' )
+	$nsub = ceil( $nsub / $this->tscrunch );
+      if( $this->fscrunch != '' )
+	$nchan = ceil( $nchan / $this->fscrunch );
+      
+      $new_data_size = $this->DetermineSubintsSize( $nsub, $nchan, $nbin, $npol );
+      
+      $new_file_size = $new_data_size + $header_size;
+      
+//       echo 'new data size is ' . $new_data_size . ' <br> ';
+//       echo 'new file size is ' . $new_file_size . ' <br> ';
+      
+      return $new_file_size;
+    }
+};
+
+
+?>
