001    package edu.nrao.sss.model.resource.evla;
002    
003    import java.io.FileNotFoundException;
004    import java.io.Reader;
005    import java.util.List;
006    
007    import javax.xml.bind.JAXBException;
008    import javax.xml.bind.annotation.XmlElement;
009    import javax.xml.bind.annotation.XmlRootElement;
010    import javax.xml.stream.XMLStreamException;
011    
012    import ca.nrc.widar.jaxb.vci.BaseBand;
013    import ca.nrc.widar.jaxb.vci.BbParams;
014    
015    import edu.nrao.sss.astronomy.PolarizationType;
016    import edu.nrao.sss.electronics.DigitalSignal;
017    import edu.nrao.sss.electronics.Signal;
018    import edu.nrao.sss.measure.Frequency;
019    import edu.nrao.sss.measure.FrequencyRange;
020    import edu.nrao.sss.util.JaxbUtility;
021    
022    /**
023     * A baseband pair of the WIDAR correlator.
024     * <p>
025     * <b>Version Info:</b>
026     * <table style="margin-left:2em">
027     *   <tr><td>$Revision: 2271 $</td></tr>
028     *   <tr><td>$Date: 2009-04-28 12:02:17 -0600 (Tue, 28 Apr 2009) $</td></tr>
029     *   <tr><td>$Author: dharland $ (last person to modify)</td></tr>
030     * </table></p>
031     * 
032     * @author David M. Harland
033     * @since 2008-06-24
034     */
035    @XmlRootElement
036    public class WidarBasebandPair
037      extends WidarBaseband
038    {
039      @XmlElement private DigitalSignal inputSignalA;
040      @XmlElement private DigitalSignal inputSignalB;
041      
042      /**
043       * Creates a new WIDAR baseband pair.
044       * @throws IllegalArgumentException
045       *   if {@code inputA} or {@code inputB} is <i>null</i>.
046       */
047      public WidarBasebandPair(DigitalSignal inputA, DigitalSignal inputB)
048      {
049        this();
050        initInput(inputA, inputB, true);
051      }
052      
053      //This is here only for persistence mechanisms
054      protected WidarBasebandPair()
055      {
056        super();
057      }
058    
059      /** Sets the input signal for this baseband. */
060      private void initInput(DigitalSignal inputA, DigitalSignal inputB, boolean forceBwUpdate)
061      {
062        if (inputA == null || inputB == null)
063          throw new IllegalArgumentException(
064            "Cannot configure correlator baseband with a NULL input signal.");
065    
066        //TODO Do we need to compare the inputs to make sure they have
067        //     same freq range?  Same init quant?  Diff polzns?
068        inputSignalA = inputA;
069        inputSignalB = inputB;
070    
071        bandwidth = inputSignalA.getCurrentRange().getWidth();
072      }
073      
074      /**
075       * Sets the input signals for this baseband pair.
076       * Classes that override this method should have
077       * <tt>super.setInput(input, input)</tt> as their first line.
078       */
079      public void setInput(DigitalSignal inputA, DigitalSignal inputB)
080      {
081        initInput(inputA, inputB, false);
082      }
083    
084      //============================================================================
085      // IDENTIFICATION
086      //============================================================================
087    
088      static String makeName(Signal signalA, Signal signalB)
089      {
090        String nameA = signalA.getName();
091        String nameB = signalB.getName();
092    
093        //Avoid pairs such as C2/A2; force to A2/C2.
094        return nameA.compareTo(nameB) <= 0 ? nameA + "/" + nameB : nameB + "/" + nameA;
095      }
096      
097      /* (non-Javadoc)
098       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getName()
099       */
100      public String getName()
101      {
102        return makeName(inputSignalA, inputSignalB);
103      }
104    
105      /* (non-Javadoc)
106       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#isSinglet()
107       */
108      public boolean isSinglet()  { return false; }
109    
110      //============================================================================
111      // FREQUENCY
112      //============================================================================
113      
114      Frequency getInputBandwidth()
115      {
116        return inputSignalA.getCurrentRange().getWidth();
117      }
118    
119      /* (non-Javadoc)
120       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getProxiedRange()
121       */
122      public FrequencyRange getProxiedRange()
123      {
124        return getProxiedRange(inputSignalA);
125      }
126    
127      /* (non-Javadoc)
128       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#proxiedRangeIsReversed()
129       */
130      public boolean proxiedRangeIsReversed()
131      {
132        return proxiedRangeIsReversed(inputSignalA);
133      }
134    
135      //============================================================================
136      // QUANTIZATION & POLARIZATION
137      //============================================================================
138    
139      /* (non-Javadoc)
140       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getInitialQuantization()
141       */
142      public int getInitialQuantization()
143      {
144        return getInitialQuantization(inputSignalA);
145      }
146      
147      /** @deprecated Use {@link #getPolarizations()}. */
148      @Deprecated
149      public PolarizationType getPolarization()
150      {
151        return getPolarizations().get(0);
152      }
153      
154      /* (non-Javadoc)
155       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getPolarizations()
156       */
157      public List<PolarizationType> getPolarizations()
158      {
159        return getPolarizations(inputSignalA, inputSignalB);
160      }
161    
162      //============================================================================
163      // PARTNERED BASEBANDS
164      //============================================================================
165    
166      /** Always returns <i>false</i>.  Baseband pairs do not have partners. */
167      public boolean isPartnerOf(WidarBaseband other)  { return false; }
168      
169      /** Always returns <i>false</i>.  Baseband pairs do not have partners. */
170      public boolean hasPartner()  { return false; }
171      
172      /** Always returns <i>null</i>.  Baseband pairs do not have partners. */
173      public WidarBaseband getPartner()  { return null; }
174    
175      /**
176       * Returns an array of two single, partnered, basebands based on this pair.
177       */
178      WidarBasebandSinglet[] toSinglePartners()
179      {
180        WidarBasebandSinglet bbA = new WidarBasebandSinglet(inputSignalA);
181        WidarBasebandSinglet bbB = new WidarBasebandSinglet(inputSignalB);
182    
183        EvlaWidarConfiguration myContainer = getEvlaWidarConfiguration();
184        
185        bbA.setEvlaWidarConfiguration(myContainer);
186        bbB.setEvlaWidarConfiguration(myContainer);
187        
188        WidarBasebandSinglet.formPartnership(bbA, bbB);
189        
190        //TODO configure singlets from this pair.  Eg, subbands
191        
192        return new WidarBasebandSinglet[] {bbA, bbB};
193      }
194      
195      //============================================================================
196      // SUBBAND
197      //============================================================================
198    
199      //============================================================================
200      // VCI ELEMENTS
201      //============================================================================
202      
203      void setWidarBbIds(BaseBand widarBB, boolean primary)
204      {
205        int[] idVciBbA = getVciBbIds(inputSignalA.getName());
206        int[] idVciBbB = getVciBbIds(inputSignalB.getName());
207        
208        int index = 0;
209        
210        if (!primary && idVciBbA.length == 2)
211          index = 1;
212        
213        widarBB.setBbA(idVciBbA[index]);
214        widarBB.setBbB(idVciBbB[index]);
215      }
216      
217      void addBbParams(List<BbParams> bbParamList, int stationId)
218      {
219        addBbParams(bbParamList, stationId, inputSignalA);
220        addBbParams(bbParamList, stationId, inputSignalB);
221      }
222      
223      //============================================================================
224      // 
225      //============================================================================
226      
227      /**
228       * Creates a new baseband from the XML data in the given file.
229       * 
230       * @param xmlFile
231       *   the name of an XML file.  This method will attempt to locate
232       *   the file by using {@link Class#getResource(String)}.
233       *                
234       * @return
235       *   a new baseband from the XML data in the given file.
236       * 
237       * @throws FileNotFoundException
238       *   if the XML file cannot be found.
239       * 
240       * @throws JAXBException
241       *   if the schema file used (if any) is malformed, if the XML file cannot be
242       *   read, or if the XML file is not schema-valid.
243       * 
244       * @throws XMLStreamException
245       *   if there is a problem opening the XML file, if the XML is not well-formed,
246       *   or for some other "unexpected processing conditions".
247       */
248      public static WidarBasebandPair fromXml(String xmlFile)
249        throws JAXBException, XMLStreamException, FileNotFoundException
250      {
251        return JaxbUtility.getSharedInstance()
252                          .xmlFileToObject(xmlFile, WidarBasebandPair.class);
253      }
254    
255      /**
256       * Creates a new baseband based on the XML data read from {@code reader}.
257       * 
258       * @param reader
259       *   the source of the XML data.
260       *   If this value is <i>null</i>, <i>null</i> is returned.
261       *               
262       * @return
263       *  a new baseband based on the XML data read from {@code reader}.
264       * 
265       * @throws XMLStreamException
266       *   if the XML is not well-formed,
267       *   or for some other "unexpected processing conditions".
268       *           
269       * @throws JAXBException
270       *   if anything else goes wrong during the transformation.
271       */
272      public static WidarBasebandPair fromXml(Reader reader)
273        throws JAXBException, XMLStreamException
274      {
275        return JaxbUtility.getSharedInstance()
276                          .readObjectAsXmlFrom(reader, WidarBasebandPair.class, null);
277      }
278    
279      //============================================================================
280      // 
281      //============================================================================
282    
283      /**
284       *  Returns a copy of this baseband.
285       *  <p>
286       *  If anything goes wrong during the cloning procedure,
287       *  a {@code RuntimeException} will be thrown.</p>
288       */
289      @Override
290      public WidarBasebandPair clone()
291      {
292        WidarBasebandPair clone = null;
293        
294        try
295        {
296          clone = (WidarBasebandPair)super.clone();
297    
298          clone.inputSignalA = this.inputSignalA.clone();
299          clone.inputSignalB = this.inputSignalB.clone();
300        }
301        catch (Exception ex)
302        {
303          throw new RuntimeException(ex);
304        }
305    
306        return clone;
307      }
308      
309      /** Returns <i>true</i> if {@code o} is equal to this baseband. */
310      @Override
311      public boolean equals(Object o)
312      {
313        //Quick exit if super class says not equal
314        if (!super.equals(o))
315          return false;
316       
317        //A safe cast if we got this far
318        WidarBasebandPair other = (WidarBasebandPair)o;
319    
320        //Equal if they have the same input signals, even if those
321        //signals are in a different order
322        return 
323          (other.inputSignalA.equals(this.inputSignalA) &&
324           other.inputSignalB.equals(this.inputSignalB))
325                               ||
326          (other.inputSignalA.equals(this.inputSignalB) &&
327           other.inputSignalB.equals(this.inputSignalA));
328      }
329    
330      /** Returns a hash code value for this baseband. */
331      @Override
332      public int hashCode()
333      {
334        //Taken from the Effective Java book by Joshua Bloch.
335        //The constants 17 & 37 are arbitrary & carry no meaning.
336        int result = super.hashCode();
337    
338        //You MUST keep this method in sync w/ the equals method
339        
340        //Want two BBs that have the same input signals to give same
341        //hashCode, even if those signals are ordered differently.
342        result = 37 * result + inputSignalA.hashCode() + inputSignalB.hashCode();
343        
344        return result;
345      }
346      
347      //============================================================================
348      // 
349      //============================================================================
350      /*
351      public static void main(String[] args)
352      {
353        WidarBuilder builder = new WidarBuilder();
354        
355        WidarBasebandPair bbp = builder.makeBasebandPair();
356    
357        try
358        {
359          bbp.writeAsXmlTo(new java.io.PrintWriter(System.out));
360        }
361        catch (Exception ex)
362        {
363          System.out.println("Trouble w/ bb.toXml.  Msg:");
364          System.out.println(ex.getMessage());
365          ex.printStackTrace();
366          
367          System.out.println("Attempting to write XML w/out schema verification:");
368          JaxbUtility.getSharedInstance().setLookForDefaultSchema(false);
369          try
370          {
371            System.out.println(bbp.toXml());
372          }
373          catch (JAXBException ex2)
374          {
375            System.out.println("Still had trouble w/ bb.toXml.  Msg:");
376            System.out.println(ex2.getMessage());
377            ex2.printStackTrace();
378          }
379        }
380        
381        BaseBand[] vciBB = bbp.toVci();
382        System.out.println(); System.out.println("-------------"); System.out.println();
383        try
384        {
385          VciJaxbUtil.writeObjectAsXmlTo(new java.io.PrintWriter(System.out), vciBB[0]);
386          if (vciBB.length > 1)
387          {
388            System.out.println(); System.out.println("-------------"); System.out.println();
389            VciJaxbUtil.writeObjectAsXmlTo(new java.io.PrintWriter(System.out), vciBB[1]);
390          }
391        }
392        catch (Exception ex)
393        {
394          throw new RuntimeException(ex);
395        }
396      }
397      */
398      /*
399      public static void main(String[] args) throws Exception
400      {
401        java.io.FileReader reader =
402          new java.io.FileReader("/export/home/calmer/dharland/JUNK/WidarBBP-IN.xml");
403        
404        WidarBasebandPair bbp = WidarBasebandPair.fromXml(reader);
405        
406        java.io.FileWriter writer =
407          new java.io.FileWriter("/export/home/calmer/dharland/JUNK/WidarBBP-OUT.xml");
408        
409        bbp.writeAsXmlTo(writer);
410      }
411      */
412    }