001 package edu.nrao.sss.model.resource.evla; 002 003 import java.awt.event.ActionEvent; 004 import java.io.FileNotFoundException; 005 import java.io.Reader; 006 import java.io.Writer; 007 import java.util.ArrayList; 008 import java.util.Date; 009 import java.util.HashSet; 010 import java.util.List; 011 import java.util.Map; 012 import java.util.Set; 013 import java.util.SortedMap; 014 import java.util.SortedSet; 015 import java.util.TreeMap; 016 import java.util.TreeSet; 017 import java.util.UUID; 018 019 import javax.xml.bind.JAXBException; 020 import javax.xml.bind.annotation.XmlElement; 021 import javax.xml.bind.annotation.XmlRootElement; 022 import javax.xml.bind.annotation.XmlType; 023 import javax.xml.datatype.XMLGregorianCalendar; 024 import javax.xml.stream.XMLStreamException; 025 026 import org.apache.log4j.Logger; 027 028 import ca.nrc.widar.jaxb.vci.BaseBand; 029 import ca.nrc.widar.jaxb.vci.BbParams; 030 import ca.nrc.widar.jaxb.vci.ListOfStations; 031 import ca.nrc.widar.jaxb.vci.Station; 032 import ca.nrc.widar.jaxb.vci.StationInputOutput; 033 import ca.nrc.widar.jaxb.vci.StationListActionType; 034 import ca.nrc.widar.jaxb.vci.SubArray; 035 import ca.nrc.widar.jaxb.vci.SubarrayActionType; 036 037 import edu.nrao.sss.electronics.DigitalSignal; 038 import edu.nrao.sss.model.resource.AntennaElectronics; 039 import edu.nrao.sss.model.resource.BasebandCollectionEvent; 040 import edu.nrao.sss.model.resource.BasebandCollectionListener; 041 import edu.nrao.sss.model.resource.CorrelationProductGroup; 042 import edu.nrao.sss.model.resource.CorrelatorBaseband; 043 import edu.nrao.sss.model.resource.CorrelatorBasebandAbs; 044 import edu.nrao.sss.model.resource.CorrelatorConfiguration; 045 import edu.nrao.sss.model.resource.CorrelatorName; 046 import edu.nrao.sss.model.resource.CorrelatorSubband; 047 import edu.nrao.sss.model.resource.ResourceSpecification; 048 import edu.nrao.sss.util.JaxbUtility; 049 050 /** 051 * The configuration of the WIDAR correlator. 052 * <p> 053 * <b>Version Info:</b> 054 * <table style="margin-left:2em"> 055 * <tr><td>$Revision: 2309 $</td></tr> 056 * <tr><td>$Date: 2009-05-14 16:46:39 -0600 (Thu, 14 May 2009) $</td></tr> 057 * <tr><td>$Author: dharland $ (last person to modify)</td></tr> 058 * </table></p> 059 * 060 * @author David M. Harland 061 * @since 2008-02-04 062 */ 063 @XmlRootElement 064 @XmlType(propOrder={"maxAntennaCount","baselineBoardPool"}) 065 public class EvlaWidarConfiguration 066 extends CorrelatorConfiguration 067 { 068 private static final Logger LOG = Logger.getLogger(EvlaWidarConfiguration.class); 069 070 private static final int EVLA_ANT_MAX = 27; 071 072 private int maxAntennaCount; 073 074 //The natural state of the basebands is to be paired, and left to its own 075 //devices the actionPerformed method of this class will be biased toward 076 //forming pairs when the signals from the antenna electronics have changed. 077 //To keep that from happening, we keep track of the BB pairs that the client 078 //has intentionally split into singlets. 079 private Set<String> pairsSplitByClient; 080 081 private BlbpPool blbpPool; 082 083 /** 084 * Constructs a new configuration that is initialized from {@code signalSrc}. 085 * 086 * @param signalSrc 087 * the antenna electronics that provide the input signals for the basebands 088 * of this configuration. 089 * 090 * @throws IllegalArgumentException 091 * if {@code signalSrc} is <i>null</i>. 092 */ 093 public EvlaWidarConfiguration(AntennaElectronics signalSrc) 094 { 095 super(signalSrc); 096 init(); 097 } 098 099 //This is here only for persistence mechanisms 100 @SuppressWarnings("unused") 101 private EvlaWidarConfiguration() 102 { 103 init(); 104 } 105 106 private void init() 107 { 108 maxAntennaCount = EVLA_ANT_MAX; 109 pairsSplitByClient = new HashSet<String>(); 110 111 blbpPool = new BlbpPool(this); 112 } 113 114 //============================================================================ 115 // IDENTIFICATION & ANTENNA COUNT 116 //============================================================================ 117 118 public CorrelatorName getName() { return CorrelatorName.WIDAR; } 119 120 /** 121 * Sets the maximum number of antennas in a subarray that may use this 122 * configuration. This configuration needs to know the maximum number 123 * of antennas to be used in an observation because many of the calculations 124 * for WIDAR depend on the number of antennas used. 125 * 126 * @param newMax 127 * the new maximum number of antennas. 128 * If this value is less than one, one will be used. 129 * If this value is greater than the number of antennas in the full array 130 * (27), 27 will be used. 131 */ 132 public void setMaxAntennaCount(int newMax) 133 { 134 if (newMax < 1) newMax = 1; 135 else if (newMax > EVLA_ANT_MAX) newMax = EVLA_ANT_MAX; 136 137 maxAntennaCount = newMax; 138 } 139 140 /** 141 * Returns the maximum number of antennas that are compatible with this 142 * configuration. See {@link #setMaxAntennaCount(int)} for more 143 * information. 144 * 145 * @return 146 * the maximum number of antennas. 147 */ 148 public int getMaxAntennaCount() 149 { 150 return maxAntennaCount; 151 } 152 153 //============================================================================ 154 // BASEBANDS 155 //============================================================================ 156 157 @Override 158 protected List<CorrelatorBaseband> getOrderedBasebands() 159 { 160 SortedMap<String, CorrelatorBaseband> nameMap = 161 new TreeMap<String, CorrelatorBaseband>(); 162 163 //Alpha name ordering, but w/ a twist related to pairs and partnered-singles 164 for (CorrelatorBaseband bb : activeBBs) 165 { 166 if (bb.isPair()) 167 { 168 nameMap.put(bb.getName(), bb); 169 } 170 else 171 { 172 WidarBasebandSinglet wbs = (WidarBasebandSinglet)bb; 173 if (!wbs.hasPartner()) 174 { 175 nameMap.put(wbs.getName(), wbs); 176 } 177 else //put name of partner w/ lower-valued name 178 { 179 String name1 = wbs.getName(); 180 String name2 = wbs.getPartner().getName(); 181 if (name1.compareTo(name2) <= 0) 182 nameMap.put(name1, wbs); 183 else 184 nameMap.put(name2, wbs.getPartner()); 185 } 186 } 187 } 188 189 //Build list from map, but account for unmapped partners 190 ArrayList<CorrelatorBaseband> result = new ArrayList<CorrelatorBaseband>(); 191 192 for (CorrelatorBaseband bb : nameMap.values()) 193 { 194 result.add(bb); 195 if (bb.isSinglet()) 196 { 197 CorrelatorBaseband p = ((WidarBasebandSinglet)bb).getPartner(); 198 if (p != null) 199 result.add(p); 200 } 201 } 202 203 return result; 204 } 205 206 /* (non-Javadoc) 207 * @see CorrelatorConfiguration#makeBasebandFrom(DigitalSignal) 208 */ 209 protected CorrelatorBaseband makeBasebandFrom(DigitalSignal ds) 210 { 211 if (ds == null) 212 return null; 213 214 WidarBaseband bb = new WidarBasebandSinglet(ds); 215 bb.setEvlaWidarConfiguration(this); 216 217 return bb; 218 } 219 220 /* (non-Javadoc) 221 * @see CorrelatorConfiguration#makeBasebandFrom(DigitalSignal) 222 */ 223 protected CorrelatorBaseband makeBasebandFrom(DigitalSignal ds1, 224 DigitalSignal ds2) 225 { 226 if (ds1 == null || ds2 == null) 227 return null; 228 229 WidarBaseband bb = new WidarBasebandPair(ds1, ds2); 230 bb.setEvlaWidarConfiguration(this); 231 232 return bb; 233 } 234 235 /** 236 * Updates this configuration by removing <tt>currentPair</tt> and 237 * replacing it with two partnered baseband singlets generated 238 * from it. 239 * 240 * @param currentPair 241 * the baseband pair to be split into partnered singles and replaced 242 * by them. 243 */ 244 public void splitBasebandPair(WidarBasebandPair currentPair) 245 { 246 //Perform the split 247 WidarBasebandSinglet[] newBBs = currentPair.toSinglePartners(); 248 249 //Remember that this was done by client request 250 pairsSplitByClient.add(currentPair.getName()); 251 252 //Update collection of active basebands. NOT updating inactiveBBs. 253 activeBBs.remove(currentPair); 254 activeBBs.add(newBBs[0]); 255 activeBBs.add(newBBs[1]); 256 257 //Notify listeners 258 List<CorrelatorBaseband> removed = new ArrayList<CorrelatorBaseband>(); 259 removed.add(currentPair); 260 261 List<CorrelatorBaseband> added = new ArrayList<CorrelatorBaseband>(); 262 added.add(newBBs[0]); 263 added.add(newBBs[1]); 264 265 notifyBasebandCollectionListeners(added, removed); 266 } 267 268 /** 269 * Updates this configuration by removing <tt>currentSinglet</tt> and 270 * its partner and replacing them with a baseband pair generated by 271 * their union. If <tt>currentSinglet</tt> has no partner, this 272 * method does nothing. 273 * <p> 274 * Note that which baseband in a tuple of partnered singles is passed 275 * to this method is significant. For example, imagine the single partnered 276 * basebands A1 and C1. If A1 is passed to this method, the A1/C1 pair 277 * will have characteristics more similar to A1 than C1, such as the 278 * decimation of the baseband into subbands.</p> 279 * 280 * @param currentSinglet 281 * the baseband singlet, along with its partner, that should be converted 282 * to a baseband pair and replaced by it. 283 */ 284 public void formPairWithPartner(WidarBasebandSinglet currentSinglet) 285 { 286 //Form the pair. Quick exit if null. 287 WidarBasebandPair newPair = currentSinglet.toPairWithPartner(); 288 if (newPair == null) 289 return; 290 291 //In case this is an un-do of a previous client split 292 pairsSplitByClient.remove(newPair.getName()); 293 294 //Update collection of active basebands. NOT updating inactiveBBs. 295 activeBBs.remove(currentSinglet); 296 activeBBs.remove(currentSinglet.getPartner()); 297 activeBBs.add(newPair); 298 299 //Notify listeners 300 List<CorrelatorBaseband> removed = new ArrayList<CorrelatorBaseband>(); 301 removed.add(currentSinglet); 302 removed.add(currentSinglet.getPartner()); 303 304 List<CorrelatorBaseband> added = new ArrayList<CorrelatorBaseband>(); 305 added.add(newPair); 306 307 notifyBasebandCollectionListeners(added, removed); 308 } 309 310 //This is called when the antenna electronics' execute method 311 //is called. 312 public void actionPerformed(ActionEvent event) 313 { 314 //Remember the names of the active BBs before we clear everything 315 Set<String> namesOfFormerlyActiveBBs = new HashSet<String>(); 316 for (CorrelatorBaseband activeBB : activeBBs) 317 namesOfFormerlyActiveBBs.add(activeBB.getName()); 318 319 //Move all BBs to inactive 320 for (CorrelatorBasebandAbs activeBB : activeBBs) 321 inactiveBBs.put(activeBB.getName(), activeBB); 322 323 activeBBs.clear(); 324 325 //Use input signals to update, or create, basebands 326 for (List<DigitalSignal> inputSignalPair : signalSource.getSignalPairs()) 327 { 328 DigitalSignal ds0 = inputSignalPair.get(0); 329 DigitalSignal ds1 = inputSignalPair.get(1); 330 331 //TODO we could put a test here to ensure at least on ds is non-null. 332 // If both are null, it's a pgmr error, because sigSrc.getSigPairs 333 // says it won't make a pair of two nulls. 334 335 if (ds1 == null) updateBaseband(ds0); 336 else if (ds0 == null) updateBaseband(ds1); 337 else updateBaseband(ds0, ds1); 338 } 339 340 //See if we activated or deactivated BBs. 341 //(This does NOT check if indiv BBs changed internally.) 342 Map<String, CorrelatorBaseband> activeBbMap = 343 new TreeMap<String, CorrelatorBaseband>(); 344 345 for (CorrelatorBaseband activeBB : activeBBs) 346 activeBbMap.put(activeBB.getName(), activeBB); 347 348 if (!namesOfFormerlyActiveBBs.equals(activeBbMap.keySet())) 349 notifyBasebandCollectionListeners(namesOfFormerlyActiveBBs, 350 activeBbMap); 351 } 352 353 //Helps actionPerformed method 354 private WidarBasebandSinglet updateBaseband(DigitalSignal inputSignal) 355 { 356 String signalName = inputSignal.getName(); 357 358 WidarBasebandSinglet bb; 359 360 //NOTE: Logic below presupposes that we've moved all BBs to inactive 361 362 //See if we already have this BB. If so, update it w/ new signal. 363 if (inactiveBBs.containsKey(signalName)) 364 { 365 bb = (WidarBasebandSinglet)inactiveBBs.remove(signalName); 366 bb.setInput(inputSignal); 367 } 368 //Make new BB if we didn't already have this one. 369 else 370 { 371 bb = new WidarBasebandSinglet(inputSignal); 372 } 373 374 bb.setEvlaWidarConfiguration(this); 375 376 activeBBs.add(bb); 377 378 return bb; 379 } 380 381 //Helps actionPerformed method 382 private void updateBaseband(DigitalSignal inputSignal0, 383 DigitalSignal inputSignal1) 384 { 385 String pairName = WidarBasebandPair.makeName(inputSignal0, inputSignal1); 386 387 //If the client has expressly decided to treat the natural pair as 388 //singlet(s), don't go ahead w/ the pairing. 389 if (pairsSplitByClient.contains(pairName)) 390 { 391 WidarBasebandSinglet bb1 = updateBaseband(inputSignal0); 392 WidarBasebandSinglet bb2 = updateBaseband(inputSignal1); 393 394 WidarBasebandSinglet.formPartnership(bb1, bb2); 395 } 396 else //update or create a BB pair 397 { 398 WidarBasebandPair bbp; 399 400 //NOTE: Logic below presupposes that we've moved all BBs to inactive 401 402 //See if we already have this BB. If so, update it w/ new signal. 403 if (inactiveBBs.containsKey(pairName)) 404 { 405 bbp = (WidarBasebandPair)inactiveBBs.remove(pairName); 406 bbp.setInput(inputSignal0, inputSignal1); 407 } 408 //Make new BB if we didn't already have this one. 409 else 410 { 411 bbp = new WidarBasebandPair(inputSignal0, inputSignal1); 412 } 413 414 bbp.setEvlaWidarConfiguration(this); 415 416 activeBBs.add(bbp); 417 } 418 } 419 420 //Called AFTER determining that notification is needed 421 private void notifyBasebandCollectionListeners(Set<String> formerBbNames, 422 Map<String, CorrelatorBaseband> currentBBs) 423 { 424 //By removing the names of the BBs before the change to our collection 425 //from the current set of names, we arrive at the names of the newly added. 426 ArrayList<CorrelatorBaseband> addedBBs = 427 new ArrayList<CorrelatorBaseband>(); 428 429 Set<String> currentBbNames = new HashSet<String>(currentBBs.keySet()); 430 431 currentBbNames.removeAll(formerBbNames); 432 433 for (String name : currentBbNames) 434 addedBBs.add(currentBBs.get(name)); 435 436 //By removing the names of the BBs after the change to our collection from 437 //the current set of names, we arrive at the names of the newly removed. 438 ArrayList<CorrelatorBaseband> removedBBs = 439 new ArrayList<CorrelatorBaseband>(); 440 441 formerBbNames = new HashSet<String>(formerBbNames); 442 443 formerBbNames.removeAll(currentBBs.keySet()); 444 445 for (String name : formerBbNames) 446 removedBBs.add(inactiveBBs.get(name)); 447 448 notifyBasebandCollectionListeners(addedBBs, removedBBs); 449 } 450 451 //Called AFTER determining that notification is needed 452 private void notifyBasebandCollectionListeners(List<CorrelatorBaseband> addedBBs, 453 List<CorrelatorBaseband> removedBBs) 454 { 455 //Create an event object and pass to listeners 456 BasebandCollectionEvent event = 457 new BasebandCollectionEvent(this, addedBBs, removedBBs); 458 459 //TODO notify listeners in a diff thread? 460 for (BasebandCollectionListener listener : bbListeners) 461 listener.basebandCollectionChanged(event); 462 } 463 464 @Override 465 protected void createdBasebandsFromPersistentStore() 466 { 467 LOG.debug("Setting container of basebands; activeBBs.size = "+activeBBs.size()); 468 469 for (CorrelatorBasebandAbs bb : activeBBs) 470 ((WidarBaseband)bb).setEvlaWidarConfiguration(this); 471 } 472 473 /** 474 * <i>This method is not yet supported.</i> 475 */ 476 public void configureFrom(ResourceSpecification scienceView) 477 { 478 throw new UnsupportedOperationException("not yet programmed"); //TODO code me 479 } 480 481 //============================================================================ 482 // BASELINE BOARD PAIRS 483 //============================================================================ 484 485 public BlbpPool getBaselineBoardPool() 486 { 487 return blbpPool; 488 } 489 490 @XmlElement 491 @SuppressWarnings("unused") //Used by JAXB and Hibernate 492 private void setBaselineBoardPool(BlbpPool newPool) 493 { 494 if (newPool != null) 495 { 496 newPool.setPoolOwner(this); 497 blbpPool = newPool; 498 } 499 } 500 501 /** Helps BlbpPool find owner of a BLBP. */ 502 WidarCorrelationProductGroup findGroup(String groupUUID) 503 { 504 for (CorrelatorBaseband bb : getBasebands()) 505 for (CorrelatorSubband sb: bb.getSubbands()) 506 for (CorrelationProductGroup cpg : sb.getCorrelationProductGroups()) 507 if (cpg.getUUID().equals(groupUUID)) 508 return (WidarCorrelationProductGroup)cpg; 509 510 return null; 511 } 512 513 //============================================================================ 514 // VCI ELEMENTS 515 //============================================================================ 516 517 /** 518 * Expresses this configuration as a VCI <tt>SubArray</tt> object. 519 * 520 * @param stationIds 521 * the IDs of the antennas to be included in the returned object. 522 * 523 * @return 524 * a VCI <tt>SubArray</tt> object based on this configuration 525 * and {@code stationIds}. 526 */ 527 public SubArray toVciSubArray(List<Integer> stationIds) 528 { 529 SubArray vciObj = new SubArray(); 530 531 vciObj.setListOfStations(toVciListOfStations(stationIds)); 532 vciObj.getStationInputOutput().add(toVciStationInputOutput()); 533 534 UUID uuid = UUID.randomUUID(); 535 536 vciObj.setAction(SubarrayActionType.CREATE); 537 vciObj.setActivationId(uuid.toString()); 538 vciObj.setMappingOrder(1); 539 vciObj.setMsgId(Math.abs(uuid.hashCode())+1); 540 vciObj.setName(signalSource.getActiveFrontEnds().first().getBand().getDisplayName()); 541 542 XMLGregorianCalendar xgc = VciJaxbUtil.getXmlGregorianFor(new Date()); 543 if (xgc != null) 544 vciObj.setTimeStamp(xgc); 545 546 return vciObj; 547 } 548 549 /** 550 * Expresses this configuration as a VCI <tt>StationInputOutput</tt> object. 551 * 552 * @return 553 * a VCI <tt>StationInputOutput</tt> object based on this configuration. 554 */ 555 public StationInputOutput toVciStationInputOutput() 556 { 557 StationInputOutput vciObj = new StationInputOutput(); 558 559 List<BaseBand> vciBBs = vciObj.getBaseBand(); 560 561 for (CorrelatorBaseband bb : getBasebands()) 562 { 563 BaseBand[] convertedBBs = ((WidarBaseband)bb).toVci(); 564 for (BaseBand convertedBB : convertedBBs) 565 vciBBs.add(convertedBB); 566 } 567 568 return vciObj; 569 } 570 571 /** 572 * Expresses this configuration as a VCI <tt>ListOfStations</tt> object. 573 * 574 * @param stationIds 575 * the IDs of the antennas to be included in the returned object. 576 * 577 * @return 578 * a VCI <tt>ListOfStations</tt> object based on this configuration 579 * and {@code stationIds}. 580 */ 581 public ListOfStations toVciListOfStations(List<Integer> stationIds) 582 { 583 ListOfStations vciObj = new ListOfStations(); 584 585 vciObj.setAction(StationListActionType.ADD); 586 587 List<Station> vciStations = vciObj.getStation(); 588 SortedSet<Integer> stationNums = new TreeSet<Integer>(stationIds); 589 590 for (int id : stationNums) 591 vciStations.add(makeStation(id)); 592 593 return vciObj; 594 } 595 596 /** 597 * Creates and populates a VCI <tt>Station</tt> object based on the given 598 * ID and the basebands held by this configuration. 599 */ 600 private Station makeStation(int stationId) 601 { 602 Station vciStation = new Station(); 603 604 vciStation.setSid(stationId); 605 606 List<BbParams> bbParamList = vciStation.getBbParams(); 607 for (CorrelatorBaseband bb : getBasebands()) 608 ((WidarBaseband)bb).addBbParams(bbParamList, stationId); 609 610 return vciStation; 611 } 612 613 //============================================================================ 614 // 615 //============================================================================ 616 617 /** 618 * Returns an XML representation of this configuration. 619 * @return an XML representation of this configuration. 620 * @throws JAXBException if anything goes wrong during the conversion to XML. 621 * @see #writeAsXmlTo(Writer) 622 */ 623 public String toXml() throws JAXBException 624 { 625 return JaxbUtility.getSharedInstance().objectToXmlString(this); 626 } 627 628 /** 629 * Writes an XML representation of this configuration to {@code writer}. 630 * @param writer the device to which XML is written. 631 * @throws JAXBException if anything goes wrong during the conversion to XML. 632 */ 633 public void writeAsXmlTo(Writer writer) throws JAXBException 634 { 635 JaxbUtility.getSharedInstance().writeObjectAsXmlTo(writer, this, null); 636 } 637 638 /** 639 * Creates a new configuration from the XML data in the given file. 640 * 641 * @param xmlFile 642 * the name of an XML file. This method will attempt to locate 643 * the file by using {@link Class#getResource(String)}. 644 * 645 * @return 646 * a new configuration from the XML data in the given file. 647 * 648 * @throws FileNotFoundException 649 * if the XML file cannot be found. 650 * 651 * @throws JAXBException 652 * if the schema file used (if any) is malformed, if the XML file cannot be 653 * read, or if the XML file is not schema-valid. 654 * 655 * @throws XMLStreamException 656 * if there is a problem opening the XML file, if the XML is not well-formed, 657 * or for some other "unexpected processing conditions". 658 */ 659 public static EvlaWidarConfiguration fromXml(String xmlFile) 660 throws JAXBException, XMLStreamException, FileNotFoundException 661 { 662 return JaxbUtility.getSharedInstance() 663 .xmlFileToObject(xmlFile, EvlaWidarConfiguration.class); 664 } 665 666 /** 667 * Creates a new configuration based on the XML data read from {@code reader}. 668 * 669 * @param reader 670 * the source of the XML data. 671 * If this value is <i>null</i>, <i>null</i> is returned. 672 * 673 * @return 674 * a new configuration based on the XML data read from {@code reader}. 675 * 676 * @throws XMLStreamException 677 * if the XML is not well-formed, 678 * or for some other "unexpected processing conditions". 679 * 680 * @throws JAXBException 681 * if anything else goes wrong during the transformation. 682 */ 683 public static EvlaWidarConfiguration fromXml(Reader reader) 684 throws JAXBException, XMLStreamException 685 { 686 return JaxbUtility.getSharedInstance() 687 .readObjectAsXmlFrom(reader, EvlaWidarConfiguration.class, null); 688 } 689 690 //============================================================================ 691 // 692 //============================================================================ 693 694 /** 695 * Returns a copy of this configuration. 696 * <p> 697 * The returned clone is <i>almost</i> a deep copy. The exceptions which 698 * prevent us from saying it <i>is</i> a deep copy are:</p> 699 * <ol> 700 * <li>No baseline board pairs are associated with the correlation product 701 * groups of the cloned configuration.</li> 702 * </ol> 703 * <p> 704 * If anything goes wrong during the cloning procedure, 705 * a {@code RuntimeException} will be thrown.</p> 706 */ 707 @Override 708 public EvlaWidarConfiguration clone() 709 { 710 EvlaWidarConfiguration clone = null; 711 712 try 713 { 714 clone = (EvlaWidarConfiguration)super.clone(); 715 716 //A new, EMPTY, pool. 717 //TODO clone pool contents? Rem: ownerIDs are the UUIDs of corr prod grps, 718 // and those UUIDs will be diff between orig and cloned configs. 719 clone.blbpPool = new BlbpPool(clone); 720 } 721 catch (Exception ex) 722 { 723 throw new RuntimeException(ex); 724 } 725 726 return clone; 727 } 728 729 /** Returns <i>true</i> if {@code o} is equal to this configuration. */ 730 @Override 731 public boolean equals(Object o) 732 { 733 //Quick exit if super class says not equal 734 if (!super.equals(o)) 735 return false; 736 737 //A safe cast if we got this far 738 EvlaWidarConfiguration other = (EvlaWidarConfiguration)o; 739 740 //Intentionally not comparing: blbpPool 741 742 return other.maxAntennaCount == this.maxAntennaCount; 743 } 744 745 /** Returns a hash code value for this configuration. */ 746 @Override 747 public int hashCode() 748 { 749 //Taken from the Effective Java book by Joshua Bloch. 750 //The constants 17 & 37 are arbitrary & carry no meaning. 751 int result = super.hashCode(); 752 753 //You MUST keep this method in sync w/ the equals method 754 755 result = 37 * result + maxAntennaCount; 756 757 return result; 758 } 759 760 //============================================================================ 761 // 762 //============================================================================ 763 /* 764 public static void main(String[] args) throws Exception 765 { 766 EvlaWidarConfiguration widar = new WidarBuilder().makeCorrelator(); 767 768 List<Integer> antennas = new ArrayList<Integer>(); 769 antennas.add(1); antennas.add(10); antennas.add(21); 770 771 //ListOfStations vciObj = widar.toVciListOfStations(antennas); 772 //StationInputOutput vciObj = widar.toVciStationInputOutput(); 773 SubArray vciObj = widar.toVciSubArray(antennas); 774 775 VciJaxbUtil.writeObjectAsXmlTo(new java.io.PrintWriter(System.out), vciObj); 776 } 777 */ 778 /* 779 public static void main(String[] args) throws Exception 780 { 781 EvlaWidarConfiguration widar = new WidarBuilder().makeCorrelator(); 782 System.out.println("widar has "+widar.getBasebands().size()+" basebands."); 783 try 784 { 785 widar.writeAsXmlTo(new java.io.PrintWriter(System.out)); 786 } 787 catch (Exception ex) 788 { 789 System.out.println("Trouble w/ widar.toXml. Msg:"); 790 System.out.println(ex.getMessage()); 791 ex.printStackTrace(); 792 793 System.out.println("Attempting to write XML w/out schema verification:"); 794 JaxbUtility.getSharedInstance().setLookForDefaultSchema(false); 795 try 796 { 797 widar.writeAsXmlTo(new java.io.PrintWriter(System.out)); 798 } 799 catch (JAXBException ex2) 800 { 801 System.out.println("Still had trouble w/ widar.toXml. Msg:"); 802 System.out.println(ex.getMessage()); 803 ex.printStackTrace(); 804 } 805 } 806 } 807 */ 808 /* 809 public static void main(String[] args) throws Exception 810 { 811 AntennaElectronics evla = new EvlaAntennaElectronics(); 812 813 EvlaWidarConfiguration widar = (EvlaWidarConfiguration) 814 CorrelatorConfiguration.makeFor(edu.nrao.sss.model.resource.CorrelatorName.WIDAR, evla); 815 816 widar.addBasebandCollectionListener 817 ( 818 new BasebandCollectionListener() 819 { 820 public void basebandCollectionChanged(BasebandCollectionEvent e) 821 { 822 System.out.println(); 823 System.out.println("CHANGE DETECTED:"); 824 for (CorrelatorBaseband bb : e.getBasebandsAdded()) 825 System.out.println(" BB Added: "+bb.getName()); 826 for (CorrelatorBaseband bb : e.getBasebandsRemoved()) 827 System.out.println(" BB Removed: "+bb.getName()); 828 } 829 } 830 ); 831 832 for (edu.nrao.sss.model.resource.ReceiverBand rb : 833 edu.nrao.sss.model.resource.TelescopeType.EVLA.getReceivers()) 834 { 835 evla.configureFor(rb); 836 evla.execute(); 837 System.out.println("\nRECEIVER "+rb); 838 for (CorrelatorBaseband bb : widar.getBasebands()) 839 System.out.println(" " + bb.toString()); 840 } 841 842 evla.configureFor(edu.nrao.sss.model.resource.ReceiverBand.EVLA_X); 843 evla.execute(); 844 845 widar.splitBasebandPair((WidarBasebandPair)widar.getBasebands().get(1)); 846 for (CorrelatorBaseband bb : widar.getBasebands()) 847 System.out.println(" " + bb.toString()); 848 849 widar.splitBasebandPair((WidarBasebandPair)widar.getBasebands().get(3)); 850 for (CorrelatorBaseband bb : widar.getBasebands()) 851 System.out.println(" " + bb.toString()); 852 853 widar.formPairWithPartner((WidarBasebandSinglet)widar.getBasebands().get(2)); 854 for (CorrelatorBaseband bb : widar.getBasebands()) 855 System.out.println(" " + bb.toString()); 856 857 System.out.println(); 858 859 for (CorrelatorBaseband bb : widar.getBasebands()) 860 for (edu.nrao.evla.widar.xml.jaxb.BaseBand b : ((WidarBaseband)bb).toVci()) 861 VciJaxbUtil.writeObjectAsXmlTo(new java.io.PrintWriter(System.out), b); 862 863 System.out.println(); 864 865 widar.writeAsXmlTo(new java.io.PrintWriter(System.out)); 866 } 867 */ 868 }