Index: /trunk/Makefile
===================================================================
--- /trunk/Makefile	(revision 88)
+++ /trunk/Makefile	(revision 89)
@@ -103,4 +103,7 @@
 	$(CXX) -o pvosummary2.x $(BASE)/pvosummary-glob.o $(HEADER) $(BLOCK) $(PSRFITS) $(UTILS) $(LIBS)
 
+s70summary : $(BASE)/s70summary.o $(HEADER) $(BLOCK) $(UTILS)
+	$(CXX) -o s70summary.x $(BASE)/s70summary.o $(HEADER) $(BLOCK)  $(UTILS) $(LIBS)
+
 testNewPSRF : $(TEST)/testNewPsrfits.o $(HEADER) $(BLOCK) $(PSRFITS) $(UTILS)
 	$(CXX) -o testNewPSRF.x $(TEST)/testNewPsrfits.o $(HEADER) $(BLOCK) $(PSRFITS) $(UTILS) $(LIBS)
Index: /trunk/Makefile.psr
===================================================================
--- /trunk/Makefile.psr	(revision 88)
+++ /trunk/Makefile.psr	(revision 89)
@@ -10,5 +10,5 @@
 
 # This forces us to use the fitsio.h file in /psr/linux/include, which
-# is of a later version than psr/packages/linux/include. This later
+# is of a later version than /psr/packages/linux/include. This later
 # version is needed so that we can use the function fits_file_exists,
 # which is not present in CFITSIO versions before v.3
@@ -19,5 +19,5 @@
 # LDFLAGS := $(LDFLAGS) -lcfitsio -lm
 
-PROGRAMS = pvoconvert.C pvosummary.C pvoconesearch.C
+PROGRAMS = pvoconvert.C pvosummary.C s70summary.C pvoconesearch.C
 
 pvoconvert.srcs = pvo-header.C  pvo-block.C  pvo-utils.C pvo-FITS.C  pvo-FITS-fileIO.C  
@@ -25,4 +25,6 @@
 pvosummary.srcs = pvo-header.C  pvo-block.C  pvo-utils.C pvo-FITS.C  pvo-FITS-fileIO.C  pvo-metadata.C
 
+s70summary.srcs = pvo-header.C  pvo-block.C  pvo-utils.C 
+
 pvoconesearch.srcs = pvo-header.C  pvo-block.C  pvo-utils.C pvo-FITS.C  pvo-FITS-fileIO.C  pvo-metadata.C
 
Index: /trunk/docs/VOimplementation.tex
===================================================================
--- /trunk/docs/VOimplementation.tex	(revision 88)
+++ /trunk/docs/VOimplementation.tex	(revision 89)
@@ -112,5 +112,11 @@
 
 The list of the columns in the existing \textsc{observations}
-mySQL table is given in the table in Appendix~\ref{app-obstable}. 
+mySQL table is given in the table in
+Appendix~\ref{app-obstable}. There is a second table,
+\textsc{observations2} that has different data in it -- it is not
+clear exactly what this data is or where it comes from (there is no
+reference to it in any of the files in the \texttt{htdocs} directory
+on \texttt{herschel}. Its setup (which is slightly different to
+\textsc{observations}) is also shown in Appendix~\ref{app-obstable}. 
 
 \subsection{Positional information}
@@ -355,4 +361,45 @@
 
 \newpage
+
+\begin{table}[h]
+\begin{tabular}{l|l|l|l|l|l}
+ Field               & Type           & Null & Key & Default      & Extra \\
+\hline
+ pulsar\_name        & varchar(16)    &      &     &              &       \\
+ filename            & varchar(32)    &      &     &              &       \\
+ raj\_hour           & int(2)         & YES  &     & 0            &       \\
+ raj\_minute         & int(2)         & YES  &     & 0            &       \\
+ raj\_second         & decimal(12,10) & YES  &     & 0.0000000000 &       \\
+ decj\_degree        & int(2)         & YES  &     & 0            &       \\
+ decj\_minute        & int(2)         & YES  &     & 0            &       \\
+ decj\_second        & decimal(12,10) & YES  &     & 0.0000000000 &       \\
+ dm                  & decimal(16,10) & YES  &     & NULL         &       \\
+ period              & decimal(32,24) & YES  &     & NULL         &       \\
+ bw                  & decimal(16,6)  & YES  &     & NULL         &       \\
+ cal\_file\_loc      & varchar(128)   & YES  &     & NULL         &       \\
+ cnfg                & varchar(128)   & YES  &     & NULL         &       \\
+ data\_loc           & varchar(128)   &      &     &              &       \\
+ data\_type          & varchar(16)    & YES  &     & NULL         &       \\
+ freq                & decimal(32,16) & YES  &     & NULL         &       \\
+ inst                & varchar(32)    & YES  &     & NULL         &       \\
+ MJD                 & decimal(32,26) & YES  &     & NULL         &       \\
+ npol                & int(6)         & YES  &     & NULL         &       \\
+ nchan               & int(6)         & YES  &     & NULL         &       \\
+ nbin                & int(6)         & YES  &     & NULL         &       \\
+ nsub                & int(6)         & YES  &     & NULL         &       \\
+ processing\_options & varchar(255)   & YES  &     & NULL         &       \\
+ is\_calibrated      & tinyint(1)     & YES  &     & 0            &       \\
+ rcvr                & varchar(16)    & YES  &     & NULL         &       \\
+ site                & varchar(8)     & YES  &     & NULL         &       \\
+ file\_size\_bytes   & int(32)        & YES  &     & NULL         &       \\
+ length              & decimal(32,20) & YES  &     & NULL         &       \\
+ obsrvr              & varchar(32)    & YES  &     & NULL         &       \\
+\end{tabular}
+\caption{Fields for the \textsc{observations2} table in the mySQL
+  database.}
+\label{tab-obs2}
+\end{table}
+
+\newpage
 \section{Proposed ``S70'' table setup}
 \label{app-s70table}
Index: /trunk/install_to_psr.sh
===================================================================
--- /trunk/install_to_psr.sh	(revision 88)
+++ /trunk/install_to_psr.sh	(revision 89)
@@ -14,4 +14,5 @@
 cp src/pvoconvert.cc      $PSRDEST/pvoconvert.C
 cp src/pvosummary.cc      $PSRDEST/pvosummary.C
+cp src/s70summary.cc      $PSRDEST/s70summary.C
 cp src/pvoconesearch.cc   $PSRDEST/pvoconesearch.C
 cp src/pvo-header.cc      $PSRDEST/pvo-header.C
Index: /trunk/sql/angsep_query.sql
===================================================================
--- /trunk/sql/angsep_query.sql	(revision 88)
+++ /trunk/sql/angsep_query.sql	(revision 89)
@@ -1,6 +1,8 @@
 use psrchive;
+--source /DATA/SITAR_1/whi550/VO/PulsarVO/sql/create_new_obs_table.sql;
+
 -- Performing a conesearch around position RA=272.46=18:09:50.4 and DEC=-19.73=-19:43:48
 -- This should pick up at least J1809-1943 and J1810-2005 (within 0.5deg of that position).
-SELECT pulsar_name,filename,data_type, period, dm, freq,
+SELECT pulsar_name,filename,data_type, period, dm, freq, 
 --	raj_hour, raj_minute, raj_second,
 --	(raj_hour+raj_minute/60.+raj_second/3600.)*15 as RA,
@@ -14,7 +16,8 @@
 		     )  
 		) ) as angsep
-, raj, decj
-FROM newobs
+--, raj, decj
+--FROM newobs
 --FROM observations
+FROM observations2
 WHERE ( degrees(acos( cos( radians( (raj_hour+raj_minute/60.+raj_second/3600.)*15 - 272.46 ) )
 			* cos(radians(abs(decj_degree)+decj_minute/60.+decj_second/3600.)*sign(decj_degree))
Index: /trunk/src/print_pm_data.cc
===================================================================
--- /trunk/src/print_pm_data.cc	(revision 88)
+++ /trunk/src/print_pm_data.cc	(revision 89)
@@ -5,5 +5,5 @@
 #include <vector>
 #include <string>
-
+using namespace std;
 enum FIELDS 
 {PROGRAM=0, VERSION, TAPENR, FILE_CNTR, BLK_CNTR, DATE, MJD, UT_STRT, LST_STRT, COORD_TYPE,
@@ -144,5 +144,5 @@
 // 	      << " " << 48.*1024.*8. / (nch[0] + nch[1])
 // 	      << " " << 48.*1024.*8. / (nch[0] + nch[1]) * blk_sec / float(grp_blk) 
-	      << " " << setw(totalFieldSize[MOVE]) << getSub(fullstring,MOVE)
+// 	      << " " << setw(totalFieldSize[MOVE]) << getSub(fullstring,MOVE)
 	      << std::endl;
   
Index: /trunk/src/pvo-FITS-fileIO.cc
===================================================================
--- /trunk/src/pvo-FITS-fileIO.cc	(revision 88)
+++ /trunk/src/pvo-FITS-fileIO.cc	(revision 89)
@@ -112,7 +112,8 @@
       this->setBeam(block.getKeyword<int>(IBEAM));
 
+      if(block.getSurveyType()==S70) this->setInitialBlock(block.getKeyword<int>(BLK_CNTR));
+      else this->setInitialBlock(1);
+
       this->setFITSname(block.getSurveyType());
-
-      this->setInitialBlock(block.getKeyword<int>(BLK_CNTR));
 
       if(this->newFile && this->fileExists()){
@@ -423,5 +424,5 @@
       double tcycle        = block.Survey().getTcycle();
       int nrcvr            = block.getKeyword<int>(NFILTER);
-      std::string obs_mode = block.Survey().getObs_mode();
+      std::string obs_mode = block.getObs_mode();
 
       std::string date_obs = 
@@ -499,5 +500,5 @@
       this->updateKeyword("STP_CRD1", stp_crd1);
       this->updateKeyword("STP_CRD2", stp_crd2);
-      this->updateKeyword("SCANLEN",  scanlen);
+//       this->updateKeyword("SCANLEN",  scanlen);
       this->updateKeyword("FD_MODE",  fd_mode);
       this->updateKeyword("FA_REQ",   fa_req);
Index: /trunk/src/pvo-FITS.cc
===================================================================
--- /trunk/src/pvo-FITS.cc	(revision 88)
+++ /trunk/src/pvo-FITS.cc	(revision 89)
@@ -51,4 +51,101 @@
     }
     //------------------------------------------------------------
+    template <typename T> int PSRFits::updateKeyword(std::string name, T value)
+    {
+      /**
+       *   Updates the keyword "name" in the current header unit, giving
+       *    it the value given by "value".
+       *   A templated function that should work for all cases.
+       */
+      int status=0;
+      fits_update_key(this->fptr, TINT, (char *)name.c_str(), &value, NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    template <> int PSRFits::updateKeyword(std::string name, int value){
+      int status=0;
+      fits_update_key(this->fptr, TINT, (char *)name.c_str(), 
+		      &value, NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    template <> int PSRFits::updateKeyword(std::string name, long value){
+      int status=0;
+      fits_update_key(this->fptr, TLONG, (char *)name.c_str(), 
+		      &value, NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    template <> int PSRFits::updateKeyword(std::string name, float value){
+      int status=0;
+      fits_update_key(this->fptr, TFLOAT, (char *)name.c_str(),
+		      &value, NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    template <> int PSRFits::updateKeyword(std::string name, double value){
+      int status=0;
+      fits_update_key(this->fptr, TDOUBLE, (char *)name.c_str(), 
+		      &value, NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    template <> int PSRFits::updateKeyword(std::string name, std::string value){
+      int status=0;
+      fits_update_key(this->fptr, TSTRING, (char *)name.c_str(), 
+		      (char *)value.c_str(), NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    template <> int PSRFits::updateKeyword(std::string name, char *value){
+      int status=0;
+      fits_update_key(this->fptr, TSTRING, (char *)name.c_str(), 
+		      value, NULL, &status);
+      if(status) this->FITSError("PSRFits::updateKeyword",status);
+      return status;
+    }
+    //------------------------------------------------------------------------
+  
+    template <typename T> int PSRFits::getKeyword(std::string name, T &value)
+    {
+      /**
+       *   Finds the keyword "name" in the current header unit,
+       *   returning the value in the "value" parameter.
+       *   A templated function that should work for all cases.
+       *  \param name The name of the keyword.
+       *  \param value The returned value of the keyword.
+       *  \return The status value from the fits_read_keyword function.
+       */
+      int status=0;
+      char keywordValue[80], keywordComment[80];
+      fits_read_keyword(this->fptr, (char *)name.c_str(), keywordValue, 
+			keywordComment, &status);
+      if(status) this->FITSError("PSRFits::getKeyword",status);
+      else{
+	std::stringstream ss;
+	ss.str(keywordValue);
+	ss >> value;
+      }
+      return status;
+    }
+    template int PSRFits::getKeyword<int>(std::string name, int &value);
+    template int PSRFits::getKeyword<long>(std::string name, long &value);
+    template int PSRFits::getKeyword<float>(std::string name, float &value);
+    template int PSRFits::getKeyword<double>(std::string name, double &value);
+    template <> int PSRFits::getKeyword<std::string>(std::string name, std::string &value){
+      int status=0;
+      char keywordValue[80], keywordComment[80];
+      fits_read_keyword(this->fptr, (char *)name.c_str(), keywordValue, 
+			keywordComment, &status);
+      if(status) this->FITSError("PSRFits::getKeyword",status);
+      else value = keywordValue;
+      if(value[0]=='\'') value.erase(0,1);
+      if(value[value.size()-1]=='\'') value.erase(value.size()-1,1);
+      return status;
+    }
+    
+  
+    //------------------------------------------------------------------------  
+
     void PSRFits::setCommandLine(int argc, char *argv[])
     {
@@ -181,9 +278,20 @@
     {
       /**
-       *   Closes the file if it is open. Adjusts the filestate variable
-       *   as well.
+       *   Closes the file if it is open. 
+       *
+       *   Sets the SCANLEN header based on the offs_sub column in the
+       *   SUBINT table, so that it has the correct scanlen (not just
+       *   the value that was requested).
+       *
+       *   Adjusts the filestate variable as well.
        */
       int status = 0;
       if(this->filestate == OPEN){
+
+	float scanlen = this->calcScanLen();
+	this->gotoPHU();
+	this->updateKeyword("SCANLEN", scanlen );
+	if(status) this->FITSError("PSRFits::closeFile",status);
+	
 	fits_close_file(this->fptr, &status);
 	if(status) this->FITSError("PSRFits::closeFile",status);
@@ -192,4 +300,5 @@
       return status;
     }
+
     //--------------------------------------------------------------------------
   
@@ -242,101 +351,4 @@
     //--------------------------------------------------------------------------
   
-    template <typename T> int PSRFits::updateKeyword(std::string name, T value)
-    {
-      /**
-       *   Updates the keyword "name" in the current header unit, giving
-       *    it the value given by "value".
-       *   A templated function that should work for all cases.
-       */
-      int status=0;
-      fits_update_key(this->fptr, TINT, name.c_str(), &value, NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    template <> int PSRFits::updateKeyword(std::string name, int value){
-      int status=0;
-      fits_update_key(this->fptr, TINT, (char *)name.c_str(), 
-		      &value, NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    template <> int PSRFits::updateKeyword(std::string name, long value){
-      int status=0;
-      fits_update_key(this->fptr, TLONG, (char *)name.c_str(), 
-		      &value, NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    template <> int PSRFits::updateKeyword(std::string name, float value){
-      int status=0;
-      fits_update_key(this->fptr, TFLOAT, (char *)name.c_str(),
-		      &value, NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    template <> int PSRFits::updateKeyword(std::string name, double value){
-      int status=0;
-      fits_update_key(this->fptr, TDOUBLE, (char *)name.c_str(), 
-		      &value, NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    template <> int PSRFits::updateKeyword(std::string name, std::string value){
-      int status=0;
-      fits_update_key(this->fptr, TSTRING, (char *)name.c_str(), 
-		      (char *)value.c_str(), NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    template <> int PSRFits::updateKeyword(std::string name, char *value){
-      int status=0;
-      fits_update_key(this->fptr, TSTRING, (char *)name.c_str(), 
-		      value, NULL, &status);
-      if(status) this->FITSError("PSRFits::updateKeyword",status);
-      return status;
-    }
-    //------------------------------------------------------------------------
-  
-    template <typename T> int PSRFits::getKeyword(std::string name, T &value)
-    {
-      /**
-       *   Finds the keyword "name" in the current header unit,
-       *   returning the value in the "value" parameter.
-       *   A templated function that should work for all cases.
-       *  \param name The name of the keyword.
-       *  \param value The returned value of the keyword.
-       *  \return The status value from the fits_read_keyword function.
-       */
-      int status=0;
-      char keywordValue[80], keywordComment[80];
-      fits_read_keyword(this->fptr, (char *)name.c_str(), keywordValue, 
-			keywordComment, &status);
-      if(status) this->FITSError("PSRFits::getKeyword",status);
-      else{
-	std::stringstream ss;
-	ss.str(keywordValue);
-	ss >> value;
-      }
-      return status;
-    }
-    template int PSRFits::getKeyword<int>(std::string name, int &value);
-    template int PSRFits::getKeyword<long>(std::string name, long &value);
-    template int PSRFits::getKeyword<float>(std::string name, float &value);
-    template int PSRFits::getKeyword<double>(std::string name, double &value);
-    template <> int PSRFits::getKeyword<std::string>(std::string name, std::string &value){
-      int status=0;
-      char keywordValue[80], keywordComment[80];
-      fits_read_keyword(this->fptr, (char *)name.c_str(), keywordValue, 
-			keywordComment, &status);
-      if(status) this->FITSError("PSRFits::getKeyword",status);
-      else value = keywordValue;
-      if(value[0]=='\'') value.erase(0,1);
-      if(value[value.size()-1]=='\'') value.erase(value.size()-1,1);
-      return status;
-    }
-    
-  
-    //------------------------------------------------------------------------  
-
     int PSRFits::getColnum(char *name)
     {
@@ -490,4 +502,29 @@
     //--------------------------------------------------------------------------
 
+    float PSRFits::calcScanLen()
+    {
+      /**
+       *  Calculate the actual scan length of the FITS file by looking
+       *  at the offs_sub column in the SUBINT table. We look at the
+       *  last value, and add half the BLK_SEC value to it to get the
+       *  total elapsed time.
+       *
+       * \return The total scan length of the FITS file.
+       */
+
+      this->gotoSubint();
+      int numrows = this->getNumRows();
+      float scanlen,oldscanlen,blksec;
+      int status = this->readColumnValue<float>("OFFS_SUB",numrows,&scanlen);
+      if(status) this->FITSError("PSRFits::calcScanLen", status);
+      status = this->readColumnValue<float>("OFFS_SUB",numrows-1,&oldscanlen);
+      if(status) this->FITSError("PSRFits::calcScanLen", status);
+      blksec = scanlen - oldscanlen;
+      scanlen += 0.5 * blksec;
+      this->gotoPHU();
+      return scanlen;
+
+    }
+
 
   }
Index: /trunk/src/pvo-FITS.hh
===================================================================
--- /trunk/src/pvo-FITS.hh	(revision 88)
+++ /trunk/src/pvo-FITS.hh	(revision 89)
@@ -230,4 +230,7 @@
       template <class T> int getKeyword(std::string name, T &value); 
 
+      /** Calculate the scan length from the offs_sub column in the SUBINT table */
+      float       calcScanLen();
+
       /** Returns the number of the named column. */
       int         getColnum(char *name);
Index: /trunk/src/pvo-block.cc
===================================================================
--- /trunk/src/pvo-block.cc	(revision 88)
+++ /trunk/src/pvo-block.cc	(revision 89)
@@ -142,4 +142,49 @@
     //--------------------------------------------------------------------------
 
+    std::string DataBlock::getObs_mode()
+    {
+      /**
+       * Returns the value of the OBS_MODE keyword as one of a number of
+       * alternative strings. This keyword should be one of PSR, CAL,
+       * or SEARCH. 
+       *
+       * The differentiation between them is done on the basis of the
+       * MOVE parameter: 0 means we are sitting on a pulsar, so it is
+       * PSR; 1 means we are doing a survey scan, so it is SEARCH.
+       *
+       * \return The OBS_MODE header keyword.
+       */
+      int move = this->getKeyword<int>(MOVE);
+      std::string output;
+      if(this->surveyType==S70){
+	switch(move){
+	case 0: output = "PSR";   break;
+	case 1:
+	default: output = "SEARCH"; break;
+	}
+      }
+      else if((this->surveyType==PM)||(this->surveyType==PH)){
+	output = "SEARCH";
+// 	switch(move){
+// 	case 90: 
+// 	case 80: 
+// 	case 70: 
+// 	case 60: 
+// 	case 50: 
+// 	case 40: 
+// 	case 30: 
+// 	case 20: 
+// 	case 10: 
+// 	case 0: output = "PSR";   break;
+// 	case 1:
+// 	case 2:
+// 	case 3:
+// 	default: output = "SEARCH"; break;
+// 	}
+      }
+      return output;
+    }
+    //--------------------------------------------------------------------------
+
     bool DataBlock::telescopeOK()
     {
Index: /trunk/src/pvo-block.hh
===================================================================
--- /trunk/src/pvo-block.hh	(revision 88)
+++ /trunk/src/pvo-block.hh	(revision 89)
@@ -74,4 +74,7 @@
       std::string getCoordMode();
 
+      /** Get the OBS_MODE header */
+      std::string getObs_mode();
+
       /** Was the telescope not moving, and tracking fine for this block? */
       bool telescopeOK();
Index: /trunk/src/pvo-utils.hh
===================================================================
--- /trunk/src/pvo-utils.hh	(revision 88)
+++ /trunk/src/pvo-utils.hh	(revision 89)
@@ -95,4 +95,17 @@
   --verbose\n";
 
+  /** Help text for s70summary -h */
+  const std::string s70summary_usage_text = 
+"Usage:\n\
+  1. s70summary \n\
+  2. s70summary -d <DIR>\n\
+---------\n\
+ s70summary  prints out some basic metadata for either all 70cm survey files in the\n\
+  current directory (example 1), or the specified directory (example 2).\n\
+ The parameters printed out are:\n\
+   RA, DEC, OBSFREQ, SCANLEN, DATE-OBS, MOVE\n\
+---------\n\
+";
+
   /** Help text for pvoconesearch -h */
   const std::string pvoconesearch_usage_text = 
Index: /trunk/src/s70summary.cc
===================================================================
--- /trunk/src/s70summary.cc	(revision 89)
+++ /trunk/src/s70summary.cc	(revision 89)
@@ -0,0 +1,157 @@
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <glob.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "pvo-block.hh"
+#include "pvo-header.hh"
+#include "pvo-utils.hh"
+using namespace PVO;
+using namespace PVO::Header;
+using namespace PVO::Block;
+using std::string;
+
+int main(int argc, char * argv[])
+{
+  /** 
+   * S70Summary is a function to print out basic information for
+   * 70cm survey tape files
+   *
+   * This program is a command-line program that looks at existing
+   * survey files and returns a summary of their starting positions, 
+   * observation times and moving flags
+   *
+   * The format of usage is: <br> 
+   * <tt>> s70summary </tt><br>
+   * to analyse all files in the current directory, or <br>
+   * <tt>> s70summary -d DIR</tt><br>
+   * to analyse all files in directory DIR
+   * Entering<br>
+   * <tt>> s70summary -h</tt><br>
+   * will give a help message, using PVO::s70summary_usage_text.
+   *
+   * The output is a list of valid files, the central RA & DEC of the
+   * first block, the central observing frequency, the requested scan
+   * length, the time/date of observation, and the moving flag.
+   * 
+   */
+
+  int c;
+  std::string directory="";
+  while (true) {
+    int option_index = 0;
+    static struct option long_options[] = {
+      {"help", 0, 0, 'h'},
+      {0, 0, 0, 0}
+    };
+
+    c = getopt_long (argc, argv, "h",
+		     long_options, &option_index);
+
+    if (c == -1) break;
+    
+    switch (c) {               
+    case 0:
+      // This is where we deal with -- options that don't have a
+      // single letter equivalent
+      break;
+    case 'h': // give help statement
+      std::cout << s70summary_usage_text;
+      return 0;
+      break;
+    case '?': // invalid option
+    case ':': // missing an argument
+      std::cout << s70summary_usage_text;
+      return 1;
+      break;
+    default:
+      std::cerr << "ERROR: getopt returned character code " <<  c << "\n";
+      break;
+    }
+
+  }
+  if (optind < argc) { 
+    // There is a non-option argument -- must be the directory to look in
+      directory = argv[optind];
+      directory += "/";
+  }
+
+  std::vector<std::string> namelist;
+  std::string filenames = directory + "*";
+  unsigned int i;
+  glob_t globbuf;
+  globbuf.gl_offs = 0;
+  glob(filenames.c_str(), GLOB_DOOFFS, NULL, &globbuf);
+  namelist.resize(globbuf.gl_pathc);
+  for(i=0;i<globbuf.gl_pathc+globbuf.gl_offs;i++) {
+    namelist[i] = globbuf.gl_pathv[i];
+  }
+
+  std::vector<std::string> goodlist;
+  for(i=0; i<namelist.size(); i++)
+    if(idSurvey(namelist[i]) == S70) goodlist.push_back(namelist[i]);
+  
+  int filenameSize = 8; // size of "FILENAME"
+  for(i=0;i<goodlist.size();i++) 
+    filenameSize = std::max(filenameSize,int(goodlist[i].size()));
+    
+  std::cout << std::setfill('-')  
+	    << std::setw(filenameSize+1+15+15+31+11+11+5) << "-";
+
+  std::cout << "\n" << std::setfill(' ') 
+	    << std::setw(filenameSize) << "FILENAME"  << " "
+	    << std::setw(14)           << "RAJ"       << " "
+	    << std::setw(14)           << "DECJ"      << " "
+	    << std::setw(10)           << "OBSFREQ"   << " "
+	    << std::setw(10)           << "SCANLEN"   << " "
+	    << std::setw(4)            << "MOVE"  << " "
+	    << std::setw(30)           << "DATE-OBS\n";
+     
+  std::cout << std::setw(filenameSize) << ""      << " "
+	    << std::setw(14)           << ""      << " "
+	    << std::setw(14)           << ""      << " "
+	    << std::setw(10)           << "[MHz]" << " "
+	    << std::setw(10)           << "[s]"   << " "
+	    << std::setw(4)            << ""      <<" "
+	    << std::setw(30)           << "\n";
+
+  std::cout<< std::setfill('-')  
+	   << std::setw(filenameSize+1+15+15+31+11+11+5) << "-";
+  std::cout<< "\n"<< std::setfill(' ') ;
+    
+  for(i=0;i<goodlist.size();i++){
+
+    std::ifstream fin;
+    fin.open(goodlist[i].c_str(), std::ios::binary);
+    DataBlock block(S70);
+    block.readBlock(fin);
+    std::string ra       = deblank(block.getKeyword<std::string>(RA));
+    std::string dec      = deblank(block.getKeyword<std::string>(DEC));
+    float scanlen        = block.getKeyword<float>(SCAN_LEN);
+    int move             = block.getKeyword<int>(MOVE);
+    std::string date_obs = 
+      makeDateObs(deblank(block.getKeyword<std::string>(DATE)),
+		  deblank(block.getKeyword<std::string>(UT))   );
+    double f0            = block.getKeyword<double>(FREQ_CHAN1);
+    double bw            = block.getKeyword<double>(CHANBW);
+    double nc            = block.getKeyword<double>(NCHAN);
+    float obsfreq        = f0 + ((nc-1)/2.) * bw;
+
+	
+    std::cout << std::setw(filenameSize) << goodlist[i] << " "
+	      << std::setw(14)           << ra          << " "
+	      << std::setw(14)           << dec         << " "
+	      << std::setprecision(4)
+	      << std::setw(10)           << obsfreq     << " "
+	      << std::setw(10)           << scanlen     << " "
+	      << std::setw(4)            << move        << " " 
+	      << std::setw(30)           << date_obs    << "\n";
+
+    fin.close();
+  }
+
+}
+
