001 package edu.nrao.sss.model.project.scan; 002 003 import java.math.BigDecimal; 004 import java.util.*; 005 006 import edu.nrao.sss.astronomy.VelocityConvention; 007 import edu.nrao.sss.astronomy.VelocityFrame; 008 import edu.nrao.sss.measure.*; 009 import edu.nrao.sss.model.project.*; 010 import edu.nrao.sss.model.proposal.Proposal; 011 import edu.nrao.sss.model.resource.*; 012 import edu.nrao.sss.model.source.*; 013 import edu.nrao.sss.util.EnumerationUtility; 014 015 /** 016 * Helper for test classes; builds scans and their components. 017 * <p> 018 * <b>Version Info:</b> 019 * <table style="margin-left:2em"> 020 * <tr><td>$Revision: 2274 $</td></tr> 021 * <tr><td>$Date: 2009-04-28 14:04:21 -0600 (Tue, 28 Apr 2009) $</td></tr> 022 * <tr><td>$Author: dharland $</td></tr> 023 * </table></p> 024 * 025 * @author David M. Harland 026 * @since 2006-10-12 027 */ 028 public class ScanBuilder 029 { 030 private static final EnumerationUtility ENUM_UTIL = 031 EnumerationUtility.getSharedInstance(); 032 033 private Random random = new Random(System.currentTimeMillis()); 034 035 private boolean setId = false; 036 private Long nextScanId = 1L; 037 038 private SourceBuilder sourceBuilder = new SourceBuilder(); 039 private ResourceBuilder resourceBuilder = new ResourceBuilder(); 040 041 //============================================================================ 042 // PUBLIC METHODS 043 //============================================================================ 044 045 /** 046 * Tells the factory methods whether or not they should set the object 047 * identifiers. 048 */ 049 public void setIdentifiers(boolean setIds) 050 { 051 setId = setIds; 052 } 053 054 055 public void makeScansFor(ScanLoop parentLoop) 056 { 057 int elementCount = 1 + random.nextInt(4); 058 059 for (int e=0; e < elementCount; e++) 060 { 061 double x = random.nextDouble(); 062 063 if (x < 0.2) 064 { 065 ScanLoop innerLoop = makeScanLoop(); 066 067 innerLoop = parentLoop.addCopyOf(innerLoop); 068 } 069 else 070 { 071 makeScanFor(parentLoop); 072 } 073 } 074 } 075 076 public ScanLoop makeScanLoop() 077 { 078 ScanLoop loop = new ScanLoop(); 079 080 initScanLoopElement(loop); 081 082 loop.setName(loop.getName() + " loop"); 083 084 loop.setIterationCount(1 + random.nextInt(9)); 085 086 int hours = 20 + random.nextInt(80); 087 loop.setMaximumDuration(new TimeDuration(new BigDecimal(hours))); 088 089 makeScansFor(loop); 090 091 return loop; 092 } 093 094 public Scan makeScan() 095 { 096 return makeScanFor((ScanLoop)null); 097 } 098 099 public Scan makeScanFor(ScanLoop parentLoop) 100 { 101 Scan newScan; 102 103 double x = random.nextDouble(); 104 105 if (x < 0.12) newScan = makeDelayScanFor(parentLoop); 106 else if (x < 0.24) newScan = makeFocusScanFor(parentLoop); 107 else if (x < 0.36) newScan = makePointingScanFor(parentLoop); 108 else if (x < 0.48) newScan = makeSwitchingScanFor(parentLoop); 109 else if (x < 0.60) newScan = makeTippingScanFor(parentLoop); 110 else newScan = makeSimpleScanFor(parentLoop); 111 112 return newScan; 113 } 114 115 private void initScan(Scan scan, ScanLoop parentLoop) 116 { 117 initScanLoopElement(scan); 118 119 if (parentLoop != null) 120 parentLoop.add(scan); 121 122 scan.setAllowOverTheTop(random.nextBoolean()); 123 scan.setApplyLastPhase(random.nextBoolean()); 124 scan.setApplyLastReferenceFocus(random.nextBoolean()); 125 scan.setApplyLastReferencePointing(random.nextBoolean()); 126 scan.setSolarObserving(random.nextBoolean()); 127 128 int max = AntennaWrap.values().length; 129 scan.setAntennaWrap(AntennaWrap.values()[random.nextInt(max)]); 130 131 List<ScanIntent> intents = new ArrayList<ScanIntent>(scan.getMode().getValidIntents()); 132 while (intents.size() > 2) 133 intents.remove(random.nextInt(intents.size())); 134 scan.setIntents(new HashSet<ScanIntent>(intents)); 135 136 Project project = scan.getProject(); 137 TelescopeType teleType = (project == null) ? null : project.getTelescope(); 138 139 //Reference antennas 140 if (TelescopeType.VLA.equals(teleType)) 141 initRefAntennas(scan); 142 143 //Source 144 Proposal proposal = (project == null) ? null : project.getProposal(); 145 if (proposal != null) 146 { 147 List<Source> sources = new ArrayList<Source>(proposal.getSources()); 148 scan.setSourceCatalogEntry(sources.get(random.nextInt(sources.size())).clone()); 149 } 150 else 151 { 152 if (random.nextDouble() < 0.667) 153 scan.setSourceCatalogEntry(sourceBuilder.makeSource(makeCode())); 154 else 155 scan.setSourceCatalogEntry(sourceBuilder.makeTable(makeCode())); 156 } 157 158 //80% of time use own resource, 10% use prev but have own, 10% use prev & have none 159 if (random.nextDouble() < 0.2) 160 { 161 scan.setUseResourceOfPriorScan(true); 162 163 if (random.nextDouble() < 0.5) 164 scan.setResource(resourceBuilder.makeResource(makeCode(), teleType)); 165 } 166 else 167 { 168 scan.setResource(resourceBuilder.makeResource(makeCode(), teleType)); 169 } 170 171 fillScanTimeSpec(scan.getTimeSpec()); 172 173 addDopplerSpecs(scan); 174 setComment(scan); 175 } 176 177 private void initRefAntennas(Scan scan) 178 { 179 AntennaSpecifier idType = ENUM_UTIL.getRandomValueFor(AntennaSpecifier.class); 180 AntennaSelection sel = scan.getReferenceAntennas(); 181 sel.setIdType(idType); 182 183 int max = idType.equals(AntennaSpecifier.ANTENNA_ID) ? 27 : 20; //20? 184 185 int count = 1 + random.nextInt(3); 186 for (int a=0; a < count; a++) 187 { 188 String id = ""; 189 if (idType.equals(AntennaSpecifier.PAD_ID)) 190 { 191 double direction = random.nextDouble(); 192 if (direction < 0.34) id = "N"; 193 else if (direction < 0.67) id = "E"; 194 else id = "W"; 195 } 196 id = id + Integer.toString(1+ random.nextInt(max)); 197 sel.addUserPick(id); 198 } 199 } 200 201 private void initScanLoopElement(ScanLoopElement sle) 202 { 203 if (setId) 204 sle.setId(nextScanId++); 205 206 Date now = new Date(); 207 sle.setCreatedOn(now); 208 sle.setLastUpdatedOn(now); 209 210 long id = 1L + (long)(random.nextInt(1000)); 211 sle.setCreatedBy(id); 212 sle.setLastUpdatedBy(id); 213 214 StringBuilder name = new StringBuilder(); 215 216 int numChars = random.nextInt(3)+3; 217 for (int i=0; i < numChars; i++) 218 name.append((char)('a'+random.nextInt(25))); 219 220 sle.setName(name.toString()); 221 222 sle.setComments("Created by ProjectBuilder.java at " + new Date()); 223 } 224 225 public SimpleScan makeSimpleScanFor(ScanLoop parentLoop) 226 { 227 SimpleScan scan = (SimpleScan)Scan.createFor(ScanMode.STANDARD_OBSERVING); 228 229 initScan(scan, parentLoop); 230 231 return scan; 232 } 233 234 public DelayScan makeDelayScanFor(ScanLoop parentLoop) 235 { 236 DelayScan scan = (DelayScan)Scan.createFor(ScanMode.AMPLITUDE_DELAY_CALIBRATING); 237 238 initScan(scan, parentLoop); 239 240 List<DelaySetting> delays = scan.getDelays(); 241 242 for (double nanos=-100.0; nanos <= +100.0; nanos += 10.0) 243 { 244 DelaySetting ds = new DelaySetting(); 245 ds.setNanoseconds(nanos); 246 ds.setTimeAtSetting(new TimeDuration("90.0", TimeUnits.SECOND)); 247 delays.add(ds); 248 } 249 250 return scan; 251 } 252 253 public FocusScan makeFocusScanFor(ScanLoop parentLoop) 254 { 255 FocusScan scan = (FocusScan)Scan.createFor(ScanMode.REFERENCE_FOCUSING); 256 257 initScan(scan, parentLoop); 258 259 List<FocusOffset> offsets = scan.getOffsets(); 260 261 for (double mm=-1.5; mm <= 1.5; mm+=0.5) 262 { 263 FocusOffset fo = new FocusOffset(); 264 fo.setOffsetLength(new Distance(BigDecimal.valueOf(mm), DistanceUnits.MILLIMETER)); 265 fo.setTimeAtOffset(new TimeDuration("20.0", TimeUnits.SECOND)); 266 offsets.add(fo); 267 } 268 269 return scan; 270 } 271 272 public PointingScan makePointingScanFor(ScanLoop parentLoop) 273 { 274 PointingScan scan = 275 (PointingScan)Scan.createFor(ScanMode.INTERFEROMETRIC_POINTING); 276 277 initScan(scan, parentLoop); 278 279 SortedSet<String> patterns = PointingScan.getNamesOfStandardPatterns(); 280 281 int choice = random.nextInt(patterns.size()); 282 283 int p = 0; 284 for (String name : patterns) 285 { 286 if (p == choice) 287 { 288 scan.setPositions(name, new TimeDuration("0.75", TimeUnits.MINUTE)); 289 break; 290 } 291 p++; 292 } 293 294 return scan; 295 } 296 297 public SwitchingScan makeSwitchingScanFor(ScanLoop parentLoop) 298 { 299 SwitchingScan scan = (SwitchingScan)Scan.createFor(ScanMode.FAST_SWITCHING); 300 301 initScan(scan, parentLoop); 302 303 scan.setApplyAutoPhasing(random.nextBoolean()); 304 scan.setTimeOnTarget(new TimeDuration(new BigDecimal(15 + random.nextInt(45)), 305 TimeUnits.SECOND)); 306 307 Project project = scan.getProject(); 308 Proposal proposal = (project == null) ? null : project.getProposal(); 309 310 List<SwitchSetting> settings = scan.getSwitchSettings(); 311 int count = 1 + random.nextInt(2); 312 for (int s=0; s < count; s++) 313 { 314 SwitchSetting ss = new SwitchSetting(); 315 316 ss.setUseForAutophasing(random.nextBoolean()); 317 ss.setTimeAtSetting(new TimeDuration(new BigDecimal(15 + random.nextInt(45)), 318 TimeUnits.SECOND)); 319 320 ss.setResource(resourceBuilder.makeResource(makeCode())); 321 322 if (proposal != null) 323 { 324 List<Source> sources = new ArrayList<Source>(proposal.getSources()); 325 ss.setSourceCatalogEntry(sources.get(random.nextInt(sources.size())).clone()); 326 } 327 else 328 ss.setSourceCatalogEntry(sourceBuilder.makeSource(makeCode())); 329 330 settings.add(ss); 331 } 332 333 return scan; 334 } 335 336 public TippingScan makeTippingScanFor(ScanLoop parentLoop) 337 { 338 TippingScan scan = (TippingScan)Scan.createFor(ScanMode.TIPPING); 339 340 initScan(scan, parentLoop); 341 342 scan.setSourceCatalogEntry(null); 343 344 scan.setAllowReverseOrder(random.nextBoolean()); 345 scan.setOrder(random.nextBoolean() ? TippingOrder.HIGH_TO_LOW 346 : TippingOrder.LOW_TO_HIGH); 347 scan.setAzimuth(new Angle(new BigDecimal(random.nextInt(360)))); 348 349 BigDecimal minEl = BigDecimal.valueOf( 5.0 + (double)random.nextInt(15)); 350 BigDecimal maxEl = BigDecimal.valueOf(70.0 + (double)random.nextInt(15)); 351 352 scan.addElevations(new Angle(minEl), new Angle(maxEl), 353 5 + random.nextInt(5), 354 new TimeDuration("2.0", TimeUnits.MINUTE)); 355 return scan; 356 } 357 358 public void fillScanTimeSpec(ScanTimeSpecification spec) 359 { 360 if (random.nextBoolean()) //DURATION 361 { 362 ScanTimeType type = ScanTimeType.ON_SOURCE_SIDEREAL; 363 364 switch (random.nextInt(4)) 365 { 366 case 0: type = ScanTimeType.ON_SOURCE_SIDEREAL; break; 367 case 1: type = ScanTimeType.ON_SOURCE_UT; break; 368 case 2: type = ScanTimeType.DURATION_SIDEREAL; break; 369 case 3: type = ScanTimeType.DURATION_UT; break; 370 } 371 int minutes = random.nextInt(50) + 10; 372 int seconds = random.nextInt(50) + 10; 373 spec.set(type, TimeDuration.parse(""+minutes+":"+seconds)); 374 } 375 else //POINT IN TIME (no longer supporting START times) 376 { 377 if (random.nextBoolean()) //LST 378 { 379 TimeOfDay tod = new TimeOfDay(); 380 tod.set(BigDecimal.valueOf(random.nextInt(86400))); 381 spec.set(ScanTimeType.STOP_LST, tod); 382 } 383 else //UT 384 { 385 Calendar cal = Calendar.getInstance(); 386 cal.set(random.nextInt(5) + 2008, 387 random.nextInt(12), 388 random.nextInt(27) + 1, 389 random.nextInt(24), 390 random.nextInt(60), 391 random.nextInt(60)); 392 spec.set(ScanTimeType.STOP_UT, cal.getTime()); 393 } 394 } 395 } 396 397 public void addDopplerSpecs(Scan scan) 398 { 399 int specCount = random.nextInt(5); 400 401 for (int s=0; s < specCount; s++) 402 scan.setDopplerSpecs(makeCode(), makeDopplerSpecs()); 403 } 404 405 public ScanDopplerSpecs makeDopplerSpecs() 406 { 407 ScanDopplerSpecs specs = new ScanDopplerSpecs(); 408 409 //Add position info to 2 of every 3 created 410 if (random.nextInt(3) % 3 != 0) 411 specs.setPosition(sourceBuilder.makeSource("").getPosition()); 412 413 //Add velocity info to 1 of every 3 created 414 if (random.nextInt(3) % 3 == 0) 415 { 416 VelocityFrame restFrame = VelocityFrame.UNKNOWN; 417 418 while (restFrame.equals(VelocityFrame.UNKNOWN) || 419 restFrame.equals(VelocityFrame.COSMIC_MICROWAVE_BACKGROUND)) 420 restFrame = ENUM_UTIL.getRandomValueFor(VelocityFrame.class); 421 422 BigDecimal kms = BigDecimal.valueOf((double)random.nextInt(10000)/10.0); 423 LinearVelocity velocity = new LinearVelocity(kms); 424 425 VelocityConvention vc = VelocityConvention.RELATIVISTIC; 426 while (vc.equals(VelocityConvention.RELATIVISTIC)) 427 vc = ENUM_UTIL.getRandomValueFor(VelocityConvention.class); 428 429 specs.setVelocity(velocity, restFrame, vc); 430 } 431 432 return specs; 433 } 434 435 private static final String[] COMMENTS = 436 { 437 "I have nothing to say, but this space was here, so I used it.", 438 "I took a stand against the man from Japan in the tan sedan who planned to ban this grand scan.", 439 "If I want your opinion, I'll give it to you.", 440 "This scan is a scam, Ma'm.", 441 "No comment." 442 }; 443 444 /** Sometimes sets comment, sometimes removes comments. */ 445 public void setComment(Scan scan) 446 { 447 int size = COMMENTS.length; 448 int index = random.nextInt(2 * size); 449 450 scan.setComments(index < size ? COMMENTS[index] : null); 451 } 452 453 //============================================================================ 454 // HELPERS 455 //============================================================================ 456 457 private String makeCode() 458 { 459 StringBuilder srcName = new StringBuilder(); 460 461 int numChars = random.nextInt(3)+3; 462 for (int i=0; i < numChars; i++) 463 srcName.append((char)('a'+random.nextInt(25))); 464 465 return srcName.toString(); 466 } 467 }