001    package edu.nrao.sss.model.source.parser;
002    
003    import java.io.IOException;
004    import java.io.Writer;
005    import java.util.List;
006    
007    import edu.nrao.sss.astronomy.CelestialCoordinateSystem;
008    import edu.nrao.sss.astronomy.CoordinateConversionException;
009    import edu.nrao.sss.astronomy.Epoch;
010    import edu.nrao.sss.astronomy.SkyPosition;
011    import edu.nrao.sss.astronomy.VelocityConvention;
012    import edu.nrao.sss.geom.EarthPosition;
013    import edu.nrao.sss.measure.LinearVelocityUnits;
014    import edu.nrao.sss.measure.LocalSiderealTime;
015    import edu.nrao.sss.model.RepositoryException;
016    import edu.nrao.sss.model.resource.TelescopeType;
017    import edu.nrao.sss.model.source.Source;
018    import edu.nrao.sss.model.source.SourceCatalog;
019    import edu.nrao.sss.model.source.SourceGroup;
020    import edu.nrao.sss.model.source.SourceVelocity;
021    import edu.nrao.sss.util.StringUtil;
022    
023    /**
024     * A writer of source catalog text files in the format used by the
025     * GBT / VLA Proposal Submission Tool (PST).  See
026     * {@link PstSourceCatalogReader} for details about this format.
027     * <p>
028     * <b>Version Info:</b>
029     * <table style="margin-left:2em">
030     *   <tr><td>$Revision$</td></tr>
031     *   <tr><td>$Date$</td></tr>
032     *   <tr><td>$Author$ (last person to modify)</td></tr>
033     * </table></p>
034     * 
035     * @author David M. Harland
036     * @since 2007-08-10
037     */
038    public class PstSourceCatalogWriter
039      extends AbstractSourceCatalogWriter
040    {
041      private static final String DELIM = ",";
042      
043      private static final EarthPosition EVLA_LOCATION =
044        TelescopeType.EVLA.getLocation();
045      
046      private LocalSiderealTime now;
047      
048      /**
049       * {@inheritDoc}
050       * <p>
051       * <b>Note</b> that this method closes the writer when it is done.
052       */
053      public boolean write(SourceCatalog catalog, Writer out)
054      {
055        boolean success = true; //overly optimistic?
056        
057        now = new LocalSiderealTime();
058        
059        try
060        {
061          for (Source source : catalog.getSources())
062          {
063            write(source, catalog, out);
064          }
065        }
066        catch (RepositoryException re)
067        {
068          putError("Problem fetching sources from catalog.  Exception msg: " +
069                   re.getMessage());
070          success = false;
071        }
072        catch (IOException ioe)
073        {
074          putError("Problem writing source information.  Exception msg: " +
075                   ioe.getMessage());
076          success = false;
077        }
078        
079        try
080        {
081          out.close();
082        }
083        catch(IOException ioe)
084        {
085          putError(0, "Error closing Writer: " + ioe.getMessage());
086          success = false;
087        }
088        
089        return success;
090      }
091      
092      private static final StringUtil SU = StringUtil.getInstance();
093      
094      /** Writes a single source to out. */
095      private void write(Source source, SourceCatalog catalog, Writer out)
096        throws IOException
097      {
098        //Name
099        out.write(source.getName());
100        out.write(DELIM);
101        
102        //RA, Dec, Epoch
103        SkyPosition pos = source.getCentralSubsource().getPosition();
104        
105        try {
106          pos = pos.toPosition(CelestialCoordinateSystem.EQUATORIAL, Epoch.J2000,
107                               EVLA_LOCATION, now);
108        }
109        catch (CoordinateConversionException cce) {
110          putError("Could not convert source " + source.getName() +
111                   " to equatorial coordinates from " + pos.getCoordinateSystem() +
112                   ".  Exception msg: " + cce.getMessage());
113        }
114        
115        final int dp = 6; //min & max digits after decimal
116        
117        out.write(' ');
118        out.write(pos.getLongitude().toStringHms(dp, dp));
119        out.write(DELIM);
120    
121        out.write(' ');
122        out.write(pos.getLatitude().toStringDms(dp, dp));
123        out.write(DELIM);
124        
125        out.write(' ');
126        out.write(pos.getEpoch().toString());
127        out.write(DELIM);
128        
129        //Velocity
130        List<SourceVelocity> svs = source.getCentralSubsource().getVelocities();
131        
132        if (svs.size() == 0)  //No velocity information
133        {
134          out.write(" 0.0");  //use 0 km/s
135          out.write(DELIM);
136          out.write(DELIM);
137        }
138        else
139        {
140          SourceVelocity sv = svs.get(0);  //arbitrary choice
141          
142          if (sv.getConvention().equals(VelocityConvention.REDSHIFT))
143          {
144            out.write(DELIM);
145            out.write(' ');
146            out.write(SU.formatNoScientificNotation(sv.getRadialVelocity().toUnits(LinearVelocityUnits.Z)));
147            out.write(DELIM);
148          }
149          else  //all other conventions use "normal" idea of velocity
150          {
151            out.write(' ');
152            out.write(SU.formatNoScientificNotation(
153                      sv.getRadialVelocity().toUnits(LinearVelocityUnits.KILOMETERS_PER_SECOND)));
154            out.write(DELIM);
155            out.write(DELIM);
156          }
157        }
158        
159        //Groups
160        for (SourceGroup sg : catalog.getGroupsThatContain(source))
161        {
162          out.write(' ');
163          out.write(sg.getName());
164          out.write(DELIM);
165        }
166        
167        out.write(StringUtil.EOL);
168      }
169    }