001    package edu.nrao.sss.model.resource.vla;
002    
003    import java.math.BigDecimal;
004    import java.util.ArrayList;
005    import java.util.List;
006    import java.util.SortedSet;
007    import java.util.TreeSet;
008    
009    import javax.xml.bind.annotation.XmlElement;
010    import javax.xml.bind.annotation.XmlRootElement;
011    
012    import edu.nrao.sss.astronomy.PolarizationType;
013    import edu.nrao.sss.electronics.DigitalSignal;
014    import edu.nrao.sss.measure.Frequency;
015    import edu.nrao.sss.measure.FrequencyRange;
016    import edu.nrao.sss.measure.FrequencyUnits;
017    import edu.nrao.sss.model.resource.CorrelatorBasebandAbs;
018    import edu.nrao.sss.model.resource.CorrelatorConfiguration;
019    import edu.nrao.sss.model.resource.CorrelatorSubband;
020    
021    /**
022     * A baseband pair of the VLA correlator.
023     * <p>
024     * This class is here for completeness but might never be used.
025     * We have a short-term mission to support the VLA correlator,
026     * but VLA support will end once WIDAR takes over.</p>
027     * <p>
028     * <b>Version Info:</b>
029     * <table style="margin-left:2em">
030     *   <tr><td>$Revision: 2271 $</td></tr>
031     *   <tr><td>$Date: 2009-04-28 12:02:17 -0600 (Tue, 28 Apr 2009) $</td></tr>
032     *   <tr><td>$Author: dharland $ (last person to modify)</td></tr>
033     * </table></p>
034     * 
035     * @author David M. Harland
036     * @since 2008-06-25
037     */
038    @XmlRootElement
039    public class VlaBasebandPair
040      extends CorrelatorBasebandAbs
041    {
042      private static final Frequency MIN_BW =
043        new Frequency("195312.5", FrequencyUnits.HERTZ);
044      
045      private static final Frequency MAX_BW =
046        new Frequency("50000000.0", FrequencyUnits.HERTZ);
047      
048      @XmlElement private DigitalSignal inputSignalA;
049      @XmlElement private DigitalSignal inputSignalB;
050      
051      private VlaConfiguration container;
052      
053      /**
054       * Helps create a new VLA baseband pair.
055       * @throws IllegalArgumentException
056       *   if {@code input} is <i>null</i>.
057       */
058      protected VlaBasebandPair(DigitalSignal inputA, DigitalSignal inputB)
059      {
060        this();
061        initInput(inputA, inputB);
062      }
063      
064      //This is here only for persistence mechanisms
065      protected VlaBasebandPair()
066      {
067        super();
068        container = null;
069      }
070    
071      /** Sets the input signal for this baseband. */
072      private void initInput(DigitalSignal inputA, DigitalSignal inputB)
073      {
074        if (inputA == null || inputB == null)
075          throw new IllegalArgumentException(
076            "Cannot configure correlator baseband with a NULL input signal.");
077    
078        //TODO Do we need to compare the inputs to make sure they have
079        //     same freq range?  Same init quant?  Diff polzns?
080        inputSignalA = inputA;
081        inputSignalB = inputB;
082      }
083    
084      //============================================================================
085      // IDENTIFICATION
086      //============================================================================
087    
088      /* (non-Javadoc)
089       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getName()
090       */
091      public String getName()
092      {
093        return inputSignalA.getName() + "/" + inputSignalB.getName();
094      }
095    
096      /* (non-Javadoc)
097       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#isSinglet()
098       */
099      public boolean isSinglet()  { return false; }
100    
101      //============================================================================
102      // CONTAINER
103      //============================================================================
104    
105      /**
106       * Returns the correlator configuration that holds this baseband.
107       * It is possible for the returned value to be <i>null</i>.
108       * If not <i>null</i>, the returned object will always be of type
109       * {@link VlaConfiguration}.
110       */
111      protected CorrelatorConfiguration getContainer()
112      {
113        return container;
114      }
115      
116      /**
117       * Sets the correlator configuration to which this baseband belongs.
118       * The {@code newContainer} is allowed to be <i>null</i>.
119       * If not <i>null</i>, the type of {@code newContainer} must be
120       * {@link VlaConfiguration}.
121       */
122      protected void setContainer(CorrelatorConfiguration newContainer)
123      {
124        container = (VlaConfiguration)newContainer;
125      }
126    
127      //============================================================================
128      // FREQUENCY
129      //============================================================================
130    
131      /* (non-Javadoc)
132       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getProxiedRange()
133       */
134      public FrequencyRange getProxiedRange()
135      {
136        return getProxiedRange(inputSignalA);
137      }
138    
139      /* (non-Javadoc)
140       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#proxiedRangeIsReversed()
141       */
142      public boolean proxiedRangeIsReversed()
143      {
144        return inputSignalA.proxiedRangeIsReversed();
145      }
146    
147      /* (non-Javadoc)
148       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getMinimumBandwidth()
149       */
150      public Frequency getMinimumBandwidth()
151      {
152        return MIN_BW.clone();
153      }
154      
155      /* (non-Javadoc)
156       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getMaximumBandwidth()
157       */
158      public Frequency getMaximumBandwidth()
159      {
160        return MAX_BW.clone();
161      }
162      
163      /* (non-Javadoc)
164       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#hasDiscreteBandwidths()
165       */
166      public boolean hasDiscreteBandwidths()
167      {
168        return true;
169      }
170      
171      /* (non-Javadoc)
172       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getAllowableBandwidths()
173       */
174      public SortedSet<Frequency> getAllowableBandwidths()
175      {
176        SortedSet<Frequency> bws = new TreeSet<Frequency>();
177        
178        BigDecimal minHz = getMinimumBandwidth().toUnits(FrequencyUnits.HERTZ);
179        
180        double maxHz =
181          getMaximumBandwidth().toUnits(FrequencyUnits.HERTZ).doubleValue();
182        
183        //Only non-negative powers-of-two multiples of min are allowed
184        //However, the frequency that corresponds to twice
185        //the minimum is not allowed.
186        bws.add(new Frequency(minHz, FrequencyUnits.HERTZ).normalize());
187        for (double hertz = minHz.doubleValue() * 4.0; hertz <= maxHz; hertz *= 2.0)
188        {
189          bws.add(new Frequency(new BigDecimal(hertz),
190                                FrequencyUnits.HERTZ).normalize());
191        }
192        return bws;
193      }
194      
195      //============================================================================
196      // QUANTIZATION & POLARIZATION
197      //============================================================================
198    
199      /* (non-Javadoc)
200       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getInitialQuantization()
201       */
202      public int getInitialQuantization()
203      {
204        return inputSignalA.getBitDepth();
205      }
206      
207      /** @deprecated Use {@link #getPolarizations()}. */
208      @Deprecated
209      public PolarizationType getPolarization()
210      {
211        return getPolarizations().get(0);
212      }
213      
214      /* (non-Javadoc)
215       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getPolarizations()
216       */
217      public List<PolarizationType> getPolarizations()
218      {
219        List<PolarizationType> answer = new ArrayList<PolarizationType>();
220        answer.add(inputSignalA.getPolarization());
221        answer.add(inputSignalB.getPolarization());
222        return answer;
223      }
224      
225      //============================================================================
226      // SUBBAND
227      //============================================================================
228    
229      /* (non-Javadoc)
230       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getMaxSubbandCount()
231       */
232      public int getMaxSubbandCount()
233      {
234        return 1;
235      }
236    
237      /* (non-Javadoc)
238       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#makeNewSubband()
239       */
240      public VlaSubband makeNewSubband()
241      {
242        return new VlaSubband();
243      }
244    
245      /* (non-Javadoc)
246       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getSubbandGrid()
247       */
248      public SortedSet<Frequency> getSubbandGrid()
249      {
250        return new TreeSet<Frequency>();
251      }
252    
253      public void addSubband(CorrelatorSubband newSubband)
254      {
255        addNewSubband((VlaSubband)newSubband);
256      }
257    
258      //============================================================================
259      // 
260      //============================================================================
261    
262      /**
263       *  Returns a copy of this baseband.
264       *  <p>
265       *  If anything goes wrong during the cloning procedure,
266       *  a {@code RuntimeException} will be thrown.</p>
267       */
268      @Override
269      public VlaBasebandPair clone()
270      {
271        VlaBasebandPair clone = null;
272        
273        try
274        {
275          clone = (VlaBasebandPair)super.clone();
276    
277          clone.inputSignalA = this.inputSignalA.clone();
278          clone.inputSignalB = this.inputSignalB.clone();
279        }
280        catch (Exception ex)
281        {
282          throw new RuntimeException(ex);
283        }
284    
285        return clone;
286      }
287      
288      /** Returns <i>true</i> if {@code o} is equal to this baseband. */
289      @Override
290      public boolean equals(Object o)
291      {
292        //Quick exit if super class says not equal
293        if (!super.equals(o))
294          return false;
295       
296        //A safe cast if we got this far
297        VlaBasebandPair other = (VlaBasebandPair)o;
298    
299        //Equal if they have the same input signals, even if those
300        //signals are in a different order
301        return 
302          (other.inputSignalA.equals(this.inputSignalA) &&
303           other.inputSignalB.equals(this.inputSignalB))
304                               ||
305          (other.inputSignalA.equals(this.inputSignalB) &&
306           other.inputSignalB.equals(this.inputSignalA));
307      }
308    
309      /** Returns a hash code value for this baseband. */
310      @Override
311      public int hashCode()
312      {
313        //Taken from the Effective Java book by Joshua Bloch.
314        //The constants 17 & 37 are arbitrary & carry no meaning.
315        int result = super.hashCode();
316        
317        //You MUST keep this method in sync w/ the equals method
318        
319        //Want two BBs that have the same input signals to give same
320        //hashCode, even if those signals are ordered differently.
321        result = 37 * result + inputSignalA.hashCode() + inputSignalB.hashCode();
322        
323        return result;
324      }
325    }