PageRenderTime 66ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/atnf/atoms/mon/gui/monpanel/Lightning.java

http://open-monica.googlecode.com/
Java | 1259 lines | 950 code | 111 blank | 198 comment | 137 complexity | 4f5f1669c5d66f8b3846ec2c0b015c31 MD5 | raw file
  1. //
  2. // Copyright (C) CSIRO Australia Telescope National Facility
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Library General Public License
  6. // as published by the Free Software Foundation; either version 2
  7. // of the License, or (at your option) any later version.
  8. package atnf.atoms.mon.gui.monpanel;
  9. import atnf.atoms.mon.gui.*;
  10. import atnf.atoms.mon.client.*;
  11. import atnf.atoms.mon.comms.MoniCAClient;
  12. import atnf.atoms.mon.PointData;
  13. import atnf.atoms.mon.SavedSetup;
  14. import atnf.atoms.time.*;
  15. import java.util.Vector;
  16. import java.util.Date;
  17. import javax.swing.*;
  18. import javax.swing.border.*;
  19. import java.awt.event.*;
  20. import java.awt.*;
  21. import java.lang.Number;
  22. import java.text.SimpleDateFormat;
  23. import java.io.PrintStream;
  24. /**
  25. * GUI display panel for Viasala lightning detector.
  26. *
  27. * @author David Brodrick
  28. * @version $Id: Lightning.java,v 1.7 2008/02/12 03:01:37 bro764 Exp $
  29. * @see MonPanel
  30. */
  31. public class
  32. Lightning
  33. extends MonPanel
  34. implements ActionListener, Runnable
  35. {
  36. static {
  37. MonPanel.registerMonPanel("Lightning Chart", Lightning.class);
  38. }
  39. ///////////////////////// NESTED CLASS ///////////////////////////////
  40. /** Nested class to provide GUI controls for configuring an ATTimeSeries
  41. * MonPanel. */
  42. public class
  43. LightningSetupPanel
  44. extends MonPanelSetupPanel
  45. implements ActionListener
  46. {
  47. /** Radio button for showing the latest frame only. */
  48. private JRadioButton itsShowLatest = new JRadioButton("Show the latest frame, updating every minute");
  49. /** Radio button for showing a short loop. */
  50. private JRadioButton itsShowLoop = new JRadioButton("Show a loop spanning the last ");
  51. /** Text field for setting delay between loop frames. */
  52. private JTextField itsFrameDelay = new JTextField("200",5);
  53. /** Text field for specifying the pause duration at the end of the loop. */
  54. private JTextField itsLoopPause = new JTextField("1500",5);
  55. /** Text field for overall loop time span, in minutes. */
  56. private JTextField itsLoopSpan = new JTextField("30",5);
  57. /** Radio button for archive replay. */
  58. private JRadioButton itsArchiveLoop = new JRadioButton("Show loop from archive:");
  59. /** Allows user to enter start time for archival mode. */
  60. private JTextField itsStart = new JTextField(16);
  61. /** Allows user to enter end time for archival mode. */
  62. private JTextField itsEnd = new JTextField(16);
  63. /** The format of the dates we parse. */
  64. private SimpleDateFormat itsFormatter
  65. = new SimpleDateFormat ("yyyy/MM/dd HH:mm");
  66. /** Options for map selection. */
  67. private String[] itsMaps = {"None"};
  68. /** Actual file names corresponding to the maps. */
  69. private String[] itsRealMaps = null;
  70. /** Combo box for map selection. */
  71. private JComboBox itsMapSelection = new JComboBox(itsMaps);
  72. /** Check box for displaying the legend. */
  73. private JCheckBox itsLegend = new JCheckBox("Show legend");
  74. /** Check box for displaying the section overlay. */
  75. private JCheckBox itsOverlay = new JCheckBox("Show map section overlay");
  76. /** Check box for displaying the total number of strikes and cloud strikes. */
  77. private JCheckBox itsShowTotals = new JCheckBox("Show total and cloud strike counts");
  78. public LightningSetupPanel(Lightning panel, JFrame frame) {
  79. super(panel, frame);
  80. ///Want to be able to add other background maps here
  81. itsRealMaps = new String[1];
  82. itsRealMaps[0] = "none";
  83. //Associate radio button group for three running modes
  84. ButtonGroup tempgroup = new ButtonGroup();
  85. tempgroup.add(itsShowLatest);
  86. tempgroup.add(itsShowLoop);
  87. tempgroup.add(itsArchiveLoop);
  88. //Setup event handlers
  89. itsShowLatest.addActionListener(this);
  90. itsShowLatest.setActionCommand("showlatest");
  91. itsShowLoop.addActionListener(this);
  92. itsShowLoop.setActionCommand("showloop");
  93. itsArchiveLoop.addActionListener(this);
  94. itsArchiveLoop.setActionCommand("archiveloop");
  95. //Select default settings
  96. itsShowLatest.doClick();
  97. itsLegend.doClick();
  98. itsOverlay.doClick();
  99. itsShowTotals.doClick();
  100. JPanel mainpanel = new JPanel();
  101. mainpanel.setLayout(new BoxLayout(mainpanel, BoxLayout.Y_AXIS));
  102. JPanel temppanel = new JPanel(new GridBagLayout());
  103. Border blackline = BorderFactory.createLineBorder(Color.black);
  104. temppanel.setBorder(BorderFactory.createTitledBorder(blackline,
  105. "Mode"));
  106. GridBagConstraints c = new GridBagConstraints();
  107. c.gridx=0;
  108. c.gridy=0;
  109. c.gridwidth=6;
  110. c.anchor=GridBagConstraints.LINE_START;
  111. temppanel.add(itsShowLatest, c);
  112. JPanel temppanel2 = new JPanel();
  113. temppanel2.add(itsShowLoop);
  114. temppanel2.add(itsLoopSpan);
  115. temppanel2.add(new JLabel(" minutes"));
  116. c.gridx=0;
  117. c.gridy=1;
  118. temppanel.add(temppanel2, c);
  119. c.gridy=2;
  120. temppanel.add(itsArchiveLoop, c);
  121. c.gridwidth=4;
  122. c.gridx=1;
  123. c.gridy=3;
  124. temppanel.add(new JLabel("Archive loop start time (yyyy/MM/dd HH:mm) "), c);
  125. c.gridwidth=1;
  126. c.gridx=5;
  127. temppanel.add(itsStart, c);
  128. c.gridwidth=4;
  129. c.gridx=1;
  130. c.gridy=4;
  131. temppanel.add(new JLabel("Archive loop end time (yyyy/MM/dd HH:mm) "), c);
  132. c.gridwidth=1;
  133. c.gridx=5;
  134. temppanel.add(itsEnd, c);
  135. mainpanel.add(temppanel);
  136. temppanel = new JPanel(new GridBagLayout());
  137. c.anchor=GridBagConstraints.LINE_START;
  138. blackline = BorderFactory.createLineBorder(Color.black);
  139. temppanel.setBorder(BorderFactory.createTitledBorder(blackline,
  140. "Loop parameters"));
  141. c.gridx=0;
  142. c.gridy=0;
  143. c.gridwidth=3;
  144. temppanel.add(new JLabel("Delay between frames in loop (ms) "), c);
  145. c.gridx=4;
  146. c.gridwidth=1;
  147. temppanel.add(itsFrameDelay, c);
  148. mainpanel.add(temppanel);
  149. c.gridx=0;
  150. c.gridy=1;
  151. c.gridwidth=3;
  152. temppanel.add(new JLabel("Pause length at end of loop (ms) "), c);
  153. c.gridx=4;
  154. c.gridwidth=1;
  155. temppanel.add(itsLoopPause, c);
  156. mainpanel.add(temppanel);
  157. temppanel = new JPanel(new GridBagLayout());
  158. c.anchor=GridBagConstraints.LINE_START;
  159. blackline = BorderFactory.createLineBorder(Color.black);
  160. temppanel.setBorder(BorderFactory.createTitledBorder(blackline,
  161. "Chart settings"));
  162. c.gridx=0;
  163. c.gridy=0;
  164. c.gridwidth=1;
  165. temppanel.add(new JLabel("Background map: "), c);
  166. c.gridx=1;
  167. temppanel.add(itsMapSelection, c);
  168. c.gridx=0;
  169. c.gridy=1;
  170. c.gridwidth=2;
  171. temppanel.add(itsLegend, c);
  172. c.gridy=2;
  173. temppanel.add(itsOverlay, c);
  174. c.gridy=3;
  175. temppanel.add(itsShowTotals, c);
  176. mainpanel.add(temppanel);
  177. add(mainpanel, BorderLayout.NORTH);
  178. add(new JPanel(), BorderLayout.CENTER);
  179. }
  180. public
  181. void
  182. actionPerformed(ActionEvent e)
  183. {
  184. super.actionPerformed(e);
  185. String cmd = e.getActionCommand();
  186. if (cmd.equals("showlatest")) {
  187. itsFrameDelay.setEnabled(false);
  188. itsLoopPause.setEnabled(false);
  189. itsStart.setEnabled(false);
  190. itsEnd.setEnabled(false);
  191. itsLoopSpan.setEnabled(false);
  192. } else if (cmd.equals("showloop")) {
  193. itsFrameDelay.setEnabled(true);
  194. itsLoopPause.setEnabled(true);
  195. itsStart.setEnabled(false);
  196. itsEnd.setEnabled(false);
  197. itsLoopSpan.setEnabled(true);
  198. } else if (cmd.equals("archiveloop")) {
  199. itsFrameDelay.setEnabled(true);
  200. itsLoopPause.setEnabled(true);
  201. itsStart.setEnabled(true);
  202. itsEnd.setEnabled(true);
  203. itsLoopSpan.setEnabled(false);
  204. }
  205. }
  206. /** Return the current setup, as determined by the GUI controls.
  207. * It provides the means of extracting the setup specified by the
  208. * user into a useable format.
  209. * @return SavedSetup specified by GUI controls, or <tt>null</tt> if
  210. * no setup can be extracted from the GUI at present. */
  211. protected
  212. SavedSetup
  213. getSetup()
  214. {
  215. SavedSetup setup = new SavedSetup("temp",
  216. "atnf.atoms.mon.gui.monpanel.Lightning");
  217. //Insert the selected map image
  218. setup.put("map", itsRealMaps[itsMapSelection.getSelectedIndex()]);
  219. if (itsShowLatest.isSelected()) {
  220. //Not looping, just showing the latest frame
  221. setup.put("mode", "latest");
  222. } else {
  223. if (itsShowLoop.isSelected()) {
  224. setup.put("mode", "realtimeloop");
  225. int loopspan=60;
  226. try {
  227. loopspan = Integer.parseInt(itsLoopSpan.getText());
  228. if (loopspan<5 || loopspan>3600) {
  229. throw new Exception();
  230. }
  231. } catch (Exception e) {
  232. JOptionPane.showMessageDialog(this,
  233. "The entry for Loop Span couldn't\n"+
  234. "be parsed, I expect an integer number\n"+
  235. "between 5 and 3600 minutes.",
  236. "Bad Loop Span Setting",
  237. JOptionPane.WARNING_MESSAGE);
  238. return null;
  239. }
  240. setup.put("loopspan", itsLoopSpan.getText());
  241. } else {
  242. setup.put("mode", "archiveloop");
  243. //Parse the archive loop start time
  244. String startstr = itsStart.getText();
  245. Date date = null;
  246. try {
  247. date = itsFormatter.parse(startstr);
  248. } catch (Exception e) { date=null; }
  249. if (date==null) {
  250. JOptionPane.showMessageDialog(this,
  251. "The Archive Loop Start Time you entered\n" +
  252. "could not be parsed. The time must\n" +
  253. "be in \"yyyy/MM/dd HH:mm\" format, eg:\n" +
  254. "\"" + itsFormatter.format(new Date()) + "\"\n",
  255. "Bad Start Time",
  256. JOptionPane.WARNING_MESSAGE);
  257. return null;
  258. }
  259. AbsTime start = AbsTime.factory(date);
  260. setup.put("loopstart", ""+start.getValue());
  261. //Next parse the archive loop end time
  262. startstr = itsEnd.getText();
  263. date = null;
  264. try {
  265. date = itsFormatter.parse(startstr);
  266. } catch (Exception e) { date=null; }
  267. if (date==null) {
  268. JOptionPane.showMessageDialog(this,
  269. "The Archive Loop End Time you entered\n" +
  270. "could not be parsed. The time must\n" +
  271. "be in \"yyyy/MM/dd HH:mm\" format, eg:\n" +
  272. "\"" + itsFormatter.format(new Date()) + "\"\n",
  273. "Bad Start Time",
  274. JOptionPane.WARNING_MESSAGE);
  275. return null;
  276. }
  277. start = AbsTime.factory(date);
  278. setup.put("loopend", ""+start.getValue());
  279. }
  280. //One of the loop mode, store loop settings
  281. int framedelay=200;
  282. try {
  283. framedelay = Integer.parseInt(itsFrameDelay.getText());
  284. if (framedelay<0 || framedelay>10000) {
  285. throw new Exception();
  286. }
  287. } catch (Exception e) {
  288. JOptionPane.showMessageDialog(this,
  289. "The entry for Frame Delay couldn't\n"+
  290. "be parsed, I expect an integer number\n"+
  291. "between 0 and 10000 milliseconds.",
  292. "Bad Frame Delay Setting",
  293. JOptionPane.WARNING_MESSAGE);
  294. return null;
  295. }
  296. setup.put("framedelay", ""+framedelay);
  297. int looppause=1500;
  298. try {
  299. looppause = Integer.parseInt(itsLoopPause.getText());
  300. if (looppause<0 || looppause>10000) {
  301. throw new Exception();
  302. }
  303. } catch (Exception e) {
  304. JOptionPane.showMessageDialog(this,
  305. "The entry for Loop Pause couldn't\n"+
  306. "be parsed, I expect an integer number\n"+
  307. "between 0 and 10000 milliseconds.",
  308. "Bad Loop Pause Setting",
  309. JOptionPane.WARNING_MESSAGE);
  310. return null;
  311. }
  312. setup.put("looppause", ""+looppause);
  313. }
  314. //Should we show an overlay of the different map segments?
  315. if (itsOverlay.isSelected()) {
  316. setup.put("overlay", "true");
  317. } else {
  318. setup.put("overlay", "false");
  319. }
  320. //Should we show the legend?
  321. if (itsLegend.isSelected()) {
  322. setup.put("legend", "true");
  323. } else {
  324. setup.put("legend", "false");
  325. }
  326. //Should we show the total number and number of cloud strikes?
  327. if (itsShowTotals.isSelected()) {
  328. setup.put("totals", "true");
  329. } else {
  330. setup.put("totals", "false");
  331. }
  332. return setup;
  333. }
  334. /** Make the controls show information about the given setup. */
  335. public
  336. void
  337. showSetup(SavedSetup setup)
  338. {
  339. try {
  340. String temp = (String)setup.get("mode");
  341. if (temp==null || temp.equals("latest")) {
  342. itsShowLatest.doClick();
  343. } else {
  344. if (temp.equals("realtimeloop")) {
  345. itsShowLoop.doClick();
  346. itsLoopSpan.setText((String)setup.get("loopspan"));
  347. } else {
  348. itsArchiveLoop.doClick();
  349. temp = (String)setup.get("loopstart");
  350. long start = Long.parseLong(temp);
  351. AbsTime atemp = AbsTime.factory(start);
  352. Date dtemp = atemp.getAsDate();
  353. itsStart.setText(itsFormatter.format(dtemp));
  354. temp = (String)setup.get("loopend");
  355. long end = Long.parseLong(temp);
  356. atemp = AbsTime.factory(end);
  357. dtemp = atemp.getAsDate();
  358. itsEnd.setText(itsFormatter.format(dtemp));
  359. }
  360. itsFrameDelay.setText((String)setup.get("framedelay"));
  361. itsLoopPause.setText((String)setup.get("looppause"));
  362. }
  363. temp = (String)setup.get("overlay");
  364. if (temp==null || temp.equals("true")) {
  365. itsOverlay.setSelected(true);
  366. } else {
  367. itsOverlay.setSelected(false);
  368. }
  369. temp = (String)setup.get("legend");
  370. if (temp==null || temp.equals("true")) {
  371. itsLegend.setSelected(true);
  372. } else {
  373. itsLegend.setSelected(false);
  374. }
  375. temp = (String)setup.get("totals");
  376. if (temp==null || temp.equals("true")) {
  377. itsShowTotals.setSelected(true);
  378. } else {
  379. itsShowTotals.setSelected(false);
  380. }
  381. temp = (String)setup.get("map");
  382. if (temp==null) {
  383. itsMapSelection.setSelectedIndex(0);
  384. } else {
  385. for (int i=0; i<itsRealMaps.length; i++) {
  386. if (itsRealMaps[i].equals(temp)) {
  387. itsMapSelection.setSelectedIndex(i);
  388. break;
  389. }
  390. }
  391. }
  392. } catch (Exception e) {
  393. System.err.println("LightningSetupPanel:showSetup: " + e.getMessage());
  394. }
  395. }
  396. }
  397. /////////////////////// END NESTED CLASS /////////////////////////////
  398. /** Reference to the setup we're currently displaying. */
  399. private SavedSetup itsSetup = null;
  400. /** Indicates if our thread should continue to run. */
  401. private boolean itsKeepRunning = true;
  402. /** Network connection to the monitor server. */
  403. private MoniCAClient itsServer = null;
  404. /** The actual array of strike data to be displayed. Each frame has
  405. * 17 data points (overhead + 8 inner octants + 8 outer octants). */
  406. private int[][] itsStrikeData = new int[0][];
  407. /** Contains timestamps for each frame of the loop. */
  408. private AbsTime[] itsStrikeTimes = null;
  409. /** Time we last tried to collect data from the server. */
  410. private AbsTime itsLastTried = null;
  411. /** The current phase of the loop (if we're displaying a loop). */
  412. private int itsLoopPhase = 0;
  413. /** Raw background map image at its native scale. */
  414. private Image itsRawBackground = null;
  415. /** Background map image scaled to the screen size. */
  416. private Image itsBackgroundMap = null;
  417. /** Current width of the scaled background image. */
  418. private int itsOldWidth = 0;
  419. /** Current height of the scaled background image. */
  420. private int itsOldHeight = 0;
  421. /** Running mode where we only show the latest frame of data. */
  422. private boolean itsShowLatest = true;
  423. /** Running mode for displaying a real-time loop. */
  424. private boolean itsShowLoop = false;
  425. /** Time span for the real-time loop. */
  426. private RelTime itsLoopSpan = null;
  427. /** Start epoch for archival loop. */
  428. private AbsTime itsLoopStart = null;
  429. /** End epoch for archival loop. */
  430. private AbsTime itsLoopEnd = null;
  431. /** Inter-frame loop delay. */
  432. private int itsFrameDelay = 200;
  433. /** Delay at end of loop. */
  434. private int itsLoopPause = 1500;
  435. /** Should we display the section overlay? */
  436. private boolean itsOverlay = true;
  437. /** Should we display the legend? */
  438. private boolean itsLegend = true;
  439. /** Should we show the total number, and number of cloud strikes. */
  440. private boolean itsShowTotals = true;
  441. /** Have we just been reinitialised with a new setup? */
  442. private boolean itsJustInitialised = false;
  443. /** Vector containing the names of the monitor points we need to use
  444. * to get the lightning strike data. First is overhead, then are the 8
  445. * outer octants clockwise from North and then the 8 inner octants
  446. * clockwise from North. The final two points are the total number of
  447. * dtected strikes and then the number of cloud strikes. */
  448. private Vector<String> itsPointNames = new Vector<String>(20);
  449. /** C'tor. */
  450. public
  451. Lightning()
  452. {
  453. setLayout(new java.awt.BorderLayout());
  454. findServer();
  455. setPreferredSize(new Dimension(550,550));
  456. setMinimumSize(new Dimension(200,200));
  457. //Should avoid hard-coding these
  458. itsPointNames.add("site.environment.lightning.overhead");
  459. itsPointNames.add("site.environment.lightning.far_N");
  460. itsPointNames.add("site.environment.lightning.far_NE");
  461. itsPointNames.add("site.environment.lightning.far_E");
  462. itsPointNames.add("site.environment.lightning.far_SE");
  463. itsPointNames.add("site.environment.lightning.far_S");
  464. itsPointNames.add("site.environment.lightning.far_SW");
  465. itsPointNames.add("site.environment.lightning.far_W");
  466. itsPointNames.add("site.environment.lightning.far_NW");
  467. itsPointNames.add("site.environment.lightning.near_N");
  468. itsPointNames.add("site.environment.lightning.near_NE");
  469. itsPointNames.add("site.environment.lightning.near_E");
  470. itsPointNames.add("site.environment.lightning.near_SE");
  471. itsPointNames.add("site.environment.lightning.near_S");
  472. itsPointNames.add("site.environment.lightning.near_SW");
  473. itsPointNames.add("site.environment.lightning.near_W");
  474. itsPointNames.add("site.environment.lightning.near_NW");
  475. itsPointNames.add("site.environment.lightning.total");
  476. itsPointNames.add("site.environment.lightning.cloud");
  477. itsPointNames.add("site.environment.lightning.uptime");
  478. //Start the data collection thread
  479. new Thread(this).start();
  480. }
  481. /** Main loop for data-update thread. */
  482. public
  483. void
  484. run()
  485. {
  486. Timer timer = new Timer(61000, this);
  487. final Lightning realthis = this;
  488. while (itsKeepRunning) {
  489. synchronized (this) {
  490. if (itsShowLatest) {
  491. if (itsJustInitialised) {
  492. itsBackgroundMap = null;
  493. itsJustInitialised = false;
  494. }
  495. itsLoopPhase = 0;
  496. itsStrikeData = new int[1][];
  497. itsStrikeTimes = new AbsTime[1];
  498. int[] newdata = new int[20];
  499. AbsTime newtime = getLatest(newdata);
  500. itsStrikeTimes[0] = newtime;
  501. itsStrikeData[0] = newdata;
  502. timer.stop();
  503. if (newtime!=null) {
  504. //Schedule for just after next expected update
  505. long currentage = (new AbsTime()).getValue() - newtime.getValue();
  506. long timetogo = 61000000 - currentage;
  507. timer = new Timer((int)(timetogo/1000), this);
  508. System.err.println("Lightning: " + timetogo/1000000 + " seconds until next update");
  509. } else {
  510. //We don't know when the next update will happen, keep trying
  511. timer = new Timer(30000, this);
  512. }
  513. //timer.stop();
  514. timer.setRepeats(true);
  515. timer.start();
  516. } else {
  517. if (itsJustInitialised) {
  518. itsBackgroundMap = null;
  519. itsJustInitialised = false;
  520. if (itsShowLoop) {
  521. //Real-time loop, so load up the recent data
  522. itsLoopEnd = new AbsTime();
  523. itsLoopStart = AbsTime.factory(itsLoopEnd.getValue()-itsLoopSpan.getValue());
  524. }
  525. getArchive(itsLoopStart, itsLoopEnd);
  526. itsLoopPhase = itsStrikeData.length-1;
  527. if (timer!=null) {
  528. timer.stop();
  529. }
  530. timer = new Timer(itsFrameDelay, this);
  531. timer.setRepeats(true);
  532. timer.start();
  533. }
  534. itsLoopPhase--;
  535. if (itsLoopPhase==0) {
  536. if (timer!=null) {
  537. timer.stop();
  538. }
  539. timer = new Timer(itsLoopPause, this);
  540. timer.setRepeats(false);
  541. timer.start();
  542. } else {
  543. if (itsLoopPhase<0) {
  544. if (itsShowLoop) {
  545. //We're running in real-time loop mode, since a loop has
  546. //just completed, now is a good time to discard any old
  547. //data and collect updated data if required
  548. AbsTime now = new AbsTime();
  549. while (itsStrikeData.length>0 &&
  550. now.getValue()-itsStrikeTimes[itsStrikeData.length-1].getValue()>itsLoopSpan.getValue())
  551. {
  552. //System.err.println("Purging oldest lightning data");
  553. int[][] newdata = new int[itsStrikeData.length-1][];
  554. AbsTime[] newtimes = new AbsTime[itsStrikeData.length-1];
  555. for (int i=0; i<itsStrikeData.length-1; i++) {
  556. newdata[i] = itsStrikeData[i];
  557. newtimes[i] = itsStrikeTimes[i];
  558. }
  559. itsStrikeData = newdata;
  560. itsStrikeTimes = newtimes;
  561. }
  562. if ((itsLastTried==null || now.getValue()-itsLastTried.getValue()>6000000) &&
  563. (itsStrikeTimes.length==0 || now.getValue()-itsStrikeTimes[0].getValue()>62000000))
  564. {
  565. //System.err.println("Requesting latest data from server");
  566. int[] newdata = new int[20];
  567. AbsTime newtime = getLatest(newdata);
  568. if (newtime!=null) {
  569. int[][] replacedata = new int[itsStrikeData.length+1][];
  570. AbsTime[] replacetimes = new AbsTime[itsStrikeData.length+1];
  571. for (int i=0; i<itsStrikeData.length; i++) {
  572. replacedata[i+1] = itsStrikeData[i];
  573. replacetimes[i+1] = itsStrikeTimes[i];
  574. }
  575. replacedata[0] = newdata;
  576. replacetimes[0] = newtime;
  577. itsStrikeData = replacedata;
  578. itsStrikeTimes = replacetimes;
  579. }
  580. }
  581. }
  582. itsLoopPhase = itsStrikeData.length-1;
  583. if (timer!=null) {
  584. timer.stop();
  585. }
  586. timer = new Timer(itsFrameDelay, this);
  587. timer.setRepeats(true);
  588. timer.start();
  589. }
  590. }
  591. }
  592. }
  593. //Redraw our display using new image - also done by event thread
  594. Runnable ud2 = new Runnable() {
  595. public void run() {
  596. //realthis.removeAll();
  597. realthis.repaint();
  598. }
  599. };
  600. try {
  601. SwingUtilities.invokeLater(ud2);
  602. } catch (Exception e) {e.printStackTrace();}
  603. //Wait here for a while
  604. synchronized (this) {
  605. try { wait(); } catch (Exception e) { e.printStackTrace(); }
  606. }
  607. }
  608. if (timer!=null) {
  609. timer.stop();
  610. }
  611. timer = null;
  612. }
  613. /** Draw our cached image of the graph to the screen. Also checks for
  614. * resize events and resizes the image if required. */
  615. public
  616. void
  617. paintComponent(Graphics g) {
  618. super.paintComponent(g);
  619. synchronized (this) {
  620. int w = getSize().width;
  621. int h = getSize().height;
  622. int minsize = (w>h)?h:w;
  623. if (itsRawBackground!=null) {
  624. if (w!=itsOldWidth || h!=itsOldHeight || itsBackgroundMap==null) {
  625. //We've been resized
  626. itsOldWidth = w;
  627. itsOldHeight = h;
  628. itsBackgroundMap = itsRawBackground.getScaledInstance(minsize, minsize, 0);
  629. }
  630. //Draw our background image to the display
  631. g.drawImage(itsBackgroundMap, 0, 0, this);
  632. }
  633. //Render the actual strike data
  634. if (itsStrikeData!=null && itsStrikeData.length>itsLoopPhase &&
  635. itsStrikeTimes!=null && itsStrikeTimes.length>itsLoopPhase &&
  636. itsLoopPhase>=0 && itsStrikeData.length==itsStrikeTimes.length &&
  637. itsStrikeData[itsLoopPhase]!=null && itsStrikeTimes[itsLoopPhase]!=null)
  638. {
  639. drawOverhead(itsStrikeData[itsLoopPhase][0], minsize, g);
  640. for (int i=0; i<8; i++) {
  641. drawOuterOctant(i, itsStrikeData[itsLoopPhase][i+1], minsize, g);
  642. drawInnerOctant(i, itsStrikeData[itsLoopPhase][i+9], minsize, g);
  643. }
  644. g.setColor(Color.black);
  645. if (itsShowTotals) {
  646. g.fillRect(0, 0, 107, 48);
  647. g.setColor(Color.white);
  648. g.drawString("" + itsStrikeData[itsLoopPhase][17] + " strikes total", 4, 29);
  649. g.drawString("" + itsStrikeData[itsLoopPhase][18] + " cloud strikes", 4, 45);
  650. } else {
  651. g.fillRect(0, 0, 107, 16);
  652. g.setColor(Color.white);
  653. }
  654. String tstring = itsStrikeTimes[itsLoopPhase].toString(AbsTime.Format.UTC_STRING);
  655. tstring = tstring.substring(5,tstring.lastIndexOf(":")) + " UT";
  656. tstring = tstring.replace('-', '/');
  657. g.drawString(tstring, 4, 13);
  658. if (itsOverlay) {
  659. drawSections(minsize, g);
  660. }
  661. if (itsLegend) {
  662. drawLegend(minsize, g);
  663. }
  664. g.setColor(Color.red);
  665. //Check the uptime
  666. if (itsStrikeData[itsLoopPhase][19]<15) {
  667. g.drawString("DETECTOR WAS POWER CYCLED", 10, minsize-40);
  668. g.drawString("DATA ACCUMULATION INCOMPLETE", 10, minsize-20);
  669. g.drawString("DETECTOR WAS POWER CYCLED", minsize-240, 20);
  670. g.drawString("DATA ACCUMULATION INCOMPLETE", minsize-240, 40);
  671. }
  672. g.setColor(Color.white);
  673. } else {
  674. if (itsOverlay) {
  675. drawSections(minsize, g);
  676. }
  677. if (itsLegend) {
  678. drawLegend(minsize, g);
  679. }
  680. g.fillRect(0, 0, 75, 16);
  681. g.setColor(Color.white);
  682. g.drawString("NO DATA!!!", 4, 13);
  683. }
  684. }
  685. }
  686. /** Get an appropriate colour for the specified strike intensity. The
  687. * colours are graded from yellow (least intense) through orange to red
  688. * (most intense). */
  689. private Color getColor(int numstrikes) {
  690. if (numstrikes==0) {
  691. return Color.black;
  692. }
  693. float red = 1.0f;
  694. float blue = 0.0f;
  695. if (numstrikes>10) {
  696. numstrikes=10;
  697. }
  698. float green = (float)(1.0 - (numstrikes/10.0));
  699. return new Color(red, green, blue);
  700. }
  701. /** Get the angle to leave between adjacent radial lines for the specified
  702. * strike intensity. More instense lightning is shown using radial lines
  703. * that are spaced more closely. */
  704. private double getAngle(int numstrikes) {
  705. if (numstrikes<3) {
  706. return (Math.PI/180.0)*8.0;
  707. } else if (numstrikes<8) {
  708. return (Math.PI/180.0)*4.0;
  709. } else {
  710. return (Math.PI/180.0)*2.0;
  711. }
  712. }
  713. /** Draw a legend to the screen. */
  714. private void
  715. drawLegend(int size, Graphics g)
  716. {
  717. final int xsize = 100;
  718. g.setColor(Color.black);
  719. g.fillRect(size-xsize, size-46, xsize, 46);
  720. g.setColor(Color.white);
  721. g.drawString("Ground", size-xsize+xsize/4, size-34);
  722. g.drawString("Strikes", size-xsize+xsize/4+3, size-21);
  723. g.drawString("1", size-xsize+5, size-18);
  724. g.drawString("10+", size-29, size-18);
  725. g.setColor(getColor(1));
  726. g.drawLine(size-xsize+5, size-1, size-xsize+5, size-15);
  727. g.drawLine(size-xsize+20, size-1, size-xsize+20, size-15);
  728. g.setColor(getColor(3));
  729. g.drawLine(size-xsize+33, size-1, size-xsize+33, size-15);
  730. g.drawLine(size-xsize+45, size-1, size-xsize+45, size-15);
  731. g.setColor(getColor(5));
  732. g.drawLine(size-xsize+56, size-1, size-xsize+56, size-15);
  733. g.drawLine(size-xsize+66, size-1, size-xsize+66, size-15);
  734. g.setColor(getColor(7));
  735. g.drawLine(size-xsize+74, size-1, size-xsize+74, size-15);
  736. g.drawLine(size-xsize+80, size-1, size-xsize+80, size-15);
  737. g.setColor(getColor(10));
  738. g.drawLine(size-xsize+85, size-1, size-xsize+85, size-15);
  739. g.drawLine(size-xsize+90, size-1, size-xsize+90, size-15);
  740. g.drawLine(size-xsize+95, size-1, size-xsize+95, size-15);
  741. g.setColor(Color.black);
  742. }
  743. /** Draw lines to indicate the different map sections. */
  744. private void
  745. drawSections(int size, Graphics g)
  746. {
  747. g.setColor(Color.black);
  748. int radius9km = (int)(9.0*size/112.0);
  749. int radius20km = (int)(20.0*size/112.0);
  750. int radius56km = (int)(56.0*size/112.0);
  751. //Draw the concentric circles
  752. g.drawOval(size/2-radius9km, size/2-radius9km, 2*radius9km, 2*radius9km);
  753. g.drawOval(size/2-radius20km, size/2-radius20km, 2*radius20km, 2*radius20km);
  754. g.drawOval(size/2-radius56km, size/2-radius56km, 2*radius56km, 2*radius56km);
  755. //Draw the radial lines
  756. for (double a=Math.PI*22.5/180.0; a<Math.PI*360.0/180.0; a+=Math.PI*45.0/180.0) {
  757. int startx = size/2 + (int)(radius9km*Math.cos(a));
  758. int starty = size/2 + (int)(radius9km*Math.sin(a));
  759. int endx = size/2 + (int)(radius56km*Math.cos(a));
  760. int endy = size/2 + (int)(radius56km*Math.sin(a));
  761. g.drawLine(startx, starty, endx, endy);
  762. }
  763. //Draw the distance markers
  764. double c=Math.cos(Math.PI*-67.5/180.0);
  765. double s=Math.sin(Math.PI*-67.5/180.0);
  766. g.fillRect((int)(size/2+radius9km*c)-8, (int)(size/2+radius9km*s)-6,31,15);
  767. g.fillRect((int)(size/2+radius20km*c)-8, (int)(size/2+radius20km*s)-6,38,15);
  768. g.fillRect((int)(size/2+radius56km*c)-8, (int)(size/2+radius56km*s)-6,38,15);
  769. g.setColor(Color.white);
  770. g.drawString("9km", (int)(size/2+radius9km*c)-6, (int)(size/2+radius9km*s)+6);
  771. g.drawString("20km", (int)(size/2+radius20km*c)-6, (int)(size/2+radius20km*s)+6);
  772. g.drawString("56km", (int)(size/2+radius56km*c)-6, (int)(size/2+radius56km*s)+6);
  773. }
  774. /** Draw strike information for the overhead zone (within 9km). */
  775. private void
  776. drawOverhead(int numstrikes, int size, Graphics g)
  777. {
  778. //don't draw anything if there are no strikes in this area
  779. if (numstrikes==0) {
  780. return;
  781. }
  782. int radius9km = (int)(9.0*size/112.0);
  783. g.setColor(getColor(numstrikes));
  784. //Draw the appropriate number of radial lines
  785. double anglestep = getAngle(numstrikes);
  786. for (double thisangle=0; thisangle<2*Math.PI; thisangle+=anglestep) {
  787. int x = (int)(size/2.0 + radius9km*Math.sin(thisangle));
  788. int y = (int)(size/2.0 - radius9km*Math.cos(thisangle));
  789. g.drawLine(size/2, size/2, x, y);
  790. }
  791. //Draw a filled rectangle as background for the number of strikes text
  792. int textwidth = numstrikes<10?17:25;
  793. g.fillRect(size/2-9, size/2-9, textwidth, 20);
  794. //Reset the colour and draw the number of strikes in black
  795. g.setColor(Color.black);
  796. g.drawString(""+numstrikes, size/2-5, size/2+5);
  797. }
  798. /** Draw strike data for the nominated "distant" range octant. */
  799. private void
  800. drawOuterOctant(int octant, int numstrikes, int size, Graphics g)
  801. {
  802. //don't draw anything if there are no strikes in this area
  803. if (numstrikes==0) {
  804. return;
  805. }
  806. g.setColor(getColor(numstrikes));
  807. double angle1 = Math.PI*(octant*45.0 - 22.5)/180.0;
  808. double angle2 = Math.PI*(octant*45.0 + 22.5)/180.0;
  809. int radius20km = (int)(20.0*size/112.0);
  810. int radius56km = (int)(56.0*size/112.0);
  811. //Draw the appropriate number of radial lines for this octant
  812. double anglestep = getAngle(numstrikes);
  813. for (double thisangle=angle1; thisangle<=angle2; thisangle+=anglestep) {
  814. int startx1 = (int)(size/2.0 + radius20km*Math.sin(thisangle));
  815. int starty1 = (int)(size/2.0 - radius20km*Math.cos(thisangle));
  816. int endx1 = (int)(size/2.0 + radius56km*Math.sin(thisangle));
  817. int endy1 = (int)(size/2.0 - radius56km*Math.cos(thisangle));
  818. g.drawLine(startx1, starty1, endx1, endy1);
  819. }
  820. //Draw a filled rectangle as background for the number of strikes text
  821. double textangle = Math.PI*octant*45.0/180.0;
  822. int textradius = (int)(38.0*size/112.0);
  823. int textx = (int)(size/2.0 + textradius*Math.sin(textangle));
  824. int texty = (int)(size/2.0 - textradius*Math.cos(textangle));
  825. int textwidth = numstrikes<10?17:25;
  826. g.fillRect(textx-4, texty-14, textwidth, 20);
  827. //Reset the colour and draw the number of strikes in black
  828. g.setColor(Color.black);
  829. g.drawString(""+numstrikes, textx, texty);
  830. }
  831. /** Draw strike data for the nominated "near" range octant. */
  832. private void
  833. drawInnerOctant(int octant, int numstrikes, int size, Graphics g)
  834. {
  835. //don't draw anything if there are no strikes in this area
  836. if (numstrikes==0) {
  837. return;
  838. }
  839. g.setColor(getColor(numstrikes));
  840. double angle1 = Math.PI*(octant*45.0 - 22.5)/180.0;
  841. double angle2 = Math.PI*(octant*45.0 + 22.5)/180.0;
  842. int radius9km = (int)(9.0*size/112.0);
  843. int radius20km = (int)(20.0*size/112.0);
  844. //Draw the appropriate number of radial lines for this octant
  845. double anglestep = getAngle(numstrikes);
  846. for (double thisangle=angle1; thisangle<=angle2; thisangle+=anglestep) {
  847. int startx1 = (int)(size/2.0 + radius9km*Math.sin(thisangle));
  848. int starty1 = (int)(size/2.0 - radius9km*Math.cos(thisangle));
  849. int endx1 = (int)(size/2.0 + radius20km*Math.sin(thisangle));
  850. int endy1 = (int)(size/2.0 - radius20km*Math.cos(thisangle));
  851. g.drawLine(startx1, starty1, endx1, endy1);
  852. }
  853. //Draw a filled rectangle as background for the number of strikes text
  854. double textangle = Math.PI*octant*45.0/180.0;
  855. int textradius = (int)(15.0*size/112.0);
  856. int textx = (int)(size/2.0 + textradius*Math.sin(textangle));
  857. int texty = (int)(size/2.0 - textradius*Math.cos(textangle));
  858. int textwidth = numstrikes<10?17:25;
  859. g.fillRect(textx-4, texty-14, textwidth, 20);
  860. //Reset the colour and draw the number of strikes in black
  861. g.setColor(Color.black);
  862. g.drawString(""+numstrikes, textx, texty);
  863. }
  864. /** Free all resources so that this MonPanel can disappear. */
  865. public
  866. void
  867. vaporise()
  868. {
  869. itsKeepRunning = false;
  870. //Awake our thread so it can clean-up and die
  871. synchronized (this) { this.notifyAll(); }
  872. }
  873. /** Called when the timer fires. */
  874. public
  875. void
  876. actionPerformed(ActionEvent e)
  877. {
  878. if (itsShowLatest) {
  879. System.err.println("Time to get the latest lightning data");
  880. }
  881. synchronized (this) { this.notifyAll(); }
  882. }
  883. /** Get the latest set of lightning strike data. The array will be
  884. * populated with strike data and the corresponding timestamp will be
  885. * returned. If no data could be obtained <tt>null</tt> will be
  886. * returned. */
  887. private
  888. AbsTime
  889. getLatest(int[] strikes) {
  890. itsLastTried = new AbsTime();
  891. Vector<PointData> newdata = null;
  892. try {
  893. newdata = itsServer.getData(itsPointNames);
  894. } catch (Exception e) {
  895. e.printStackTrace();
  896. return null;
  897. }
  898. if (newdata==null) {
  899. return null;
  900. }
  901. AbsTime tstamp = null;
  902. for (int i=0; i<20; i++) {
  903. PointData pd = newdata.get(i);
  904. if (pd==null) {
  905. return null;
  906. }
  907. Number n = null;
  908. if (pd.getData() instanceof Number) {
  909. n = (Number)pd.getData();
  910. } else if (pd.getData() instanceof RelTime) {
  911. n = new Integer((int)(((RelTime)pd.getData()).getValue()/60000000));
  912. }
  913. if (n==null) {
  914. return null;
  915. }
  916. strikes[i] = n.intValue();
  917. if (tstamp==null) {
  918. tstamp=pd.getTimestamp();
  919. if (itsStrikeTimes!=null && itsStrikeTimes.length>0 &&
  920. itsStrikeTimes[0]!=null &&
  921. tstamp.getValue()==itsStrikeTimes[0].getValue())
  922. {
  923. //Oi! this is the same data you gave us last time!
  924. return null;
  925. }
  926. }
  927. }
  928. return tstamp;
  929. }
  930. /** Get lightning strike data during the specified range of times.
  931. * the internal structures itsStrikeData and itsStrikeTimes are filled
  932. * out according to the data. */
  933. private
  934. void
  935. getArchive(AbsTime start, AbsTime end)
  936. {
  937. //System.err.println("Making archive request:");
  938. //System.err.println("\t" + start.toString(AbsTime.Format.UTC_STRING));
  939. //System.err.println("\t" + end.toString(AbsTime.Format.UTC_STRING));
  940. try {
  941. boolean first = true;
  942. //We retrieve each monitor points archival data in turn
  943. for (int i=0; i<20; i++) {
  944. Vector<PointData> thisdata = itsServer.getArchiveData(itsPointNames.get(i),
  945. itsLoopStart, itsLoopEnd);
  946. if (i==19 && (thisdata==null || thisdata.size()<itsStrikeData[0].length))
  947. {
  948. //No uptime info was available, assume it is >15 minutes
  949. for (int j=0; j<itsStrikeData.length; j++) {
  950. itsStrikeData[j][19] = 16+5*j;
  951. }
  952. } else {
  953. if (first) {
  954. first = false;
  955. itsStrikeData = new int[thisdata.size()][];
  956. for (int j=0; j<thisdata.size(); j++) {
  957. itsStrikeData[j] = new int[20];
  958. }
  959. itsStrikeTimes = new AbsTime[thisdata.size()];
  960. for (int j=0; j<thisdata.size(); j++) {
  961. AbsTime thistime = ((PointData)(thisdata.get(j))).getTimestamp();
  962. if (thistime==null) {
  963. throw new Exception();
  964. }
  965. itsStrikeTimes[thisdata.size()-j-1] = thistime;
  966. }
  967. }
  968. for (int j=0; j<thisdata.size(); j++) {
  969. Number n = null;
  970. if (((PointData)(thisdata.get(j))).getData() instanceof Number) {
  971. n = (Number)((PointData)(thisdata.get(j))).getData();
  972. } else if (((PointData)(thisdata.get(j))).getData() instanceof RelTime) {
  973. n = new Integer((int)(((RelTime)((PointData)(thisdata.get(j))).getData()).getValue()/60000000));
  974. }
  975. if (n==null) {
  976. throw new Exception();
  977. }
  978. itsStrikeData[thisdata.size()-j-1][i] = n.intValue();
  979. }
  980. }
  981. }
  982. } catch (Exception e) {
  983. e.printStackTrace();
  984. itsStrikeData = new int[0][];
  985. itsStrikeTimes = new AbsTime[0];;
  986. }
  987. }
  988. /** Clear any current setup. */
  989. public synchronized
  990. void
  991. blankSetup()
  992. {
  993. synchronized (this) { this.notifyAll(); }
  994. }
  995. /** Configure this MonPanel to use the specified setup. This method can
  996. * be used to restore saved states, eg what monitor points to graph and
  997. * over what time range.
  998. * @param setup class-specific setup information.
  999. * @return <tt>true</tt> if setup could be parsed or <tt>false</tt> if
  1000. * there was a problem and the setup cannot be used.
  1001. */
  1002. public synchronized
  1003. boolean
  1004. loadSetup(SavedSetup setup)
  1005. {
  1006. synchronized (this) {
  1007. try {
  1008. //check if the setup is suitable for our class
  1009. if (!setup.checkClass(this)) {
  1010. System.err.println("Lightning:loadSetup: setup not for "
  1011. + this.getClass().getName());
  1012. return false;
  1013. }
  1014. //the copy of the setup held by the frame is now incorrect
  1015. if (itsFrame instanceof MonFrame) {
  1016. ((MonFrame)itsFrame).itsSetup=null;
  1017. }
  1018. /* String mapname = (String)setup.get("map");
  1019. if (mapname==null || mapname.equals("") || mapname.equals("none")) {
  1020. itsRawBackground = null;
  1021. } else {
  1022. String imagename = "atnf/atoms/mon/gui/monpanel/" + mapname;
  1023. URL url = this.getClass().getClassLoader().getResource(imagename);
  1024. itsRawBackground = Toolkit.getDefaultToolkit().getImage(url);
  1025. }*/
  1026. String temp = (String)setup.get("legend");
  1027. if (temp==null || temp.equals("true")) {
  1028. itsLegend = true;
  1029. } else {
  1030. itsLegend = false;
  1031. }
  1032. temp = (String)setup.get("overlay");
  1033. if (temp==null || temp.equals("true")) {
  1034. itsOverlay = true;
  1035. } else {
  1036. itsOverlay = false;
  1037. }
  1038. temp = (String)setup.get("totals");
  1039. if (temp==null || temp.equals("true")) {
  1040. itsShowTotals = true;
  1041. } else {
  1042. itsShowTotals = false;
  1043. }
  1044. temp = (String)setup.get("mode");
  1045. if (temp.equals("latest")) {
  1046. itsShowLatest = true;
  1047. itsShowLoop = false;
  1048. } else {
  1049. if (temp.equals("realtimeloop")) {
  1050. itsShowLoop = true;
  1051. itsShowLatest = false;
  1052. int nummins = Integer.parseInt((String)setup.get("loopspan"));
  1053. itsLoopSpan = RelTime.factory(nummins*60000000l);
  1054. } else if (temp.equals("archiveloop")) {
  1055. itsShowLoop = false;
  1056. itsShowLatest = false;
  1057. itsLoopStart = AbsTime.factory(Long.parseLong((String)setup.get("loopstart")));
  1058. itsLoopEnd = AbsTime.factory(Long.parseLong((String)setup.get("loopend")));
  1059. }
  1060. //Get the other loop parameters
  1061. temp = (String)setup.get("framedelay");
  1062. itsFrameDelay = Integer.parseInt(temp);
  1063. temp = (String)setup.get("looppause");
  1064. itsLoopPause = Integer.parseInt(temp);
  1065. }
  1066. itsSetup = setup;
  1067. itsJustInitialised = true;
  1068. //Make thread up so it can use new settings
  1069. synchronized (this) { this.notifyAll(); }
  1070. } catch (Exception e) {
  1071. System.err.println("Lightning:loadSetup: " + e.getClass().getName()
  1072. + " " + e.getMessage());
  1073. e.printStackTrace();
  1074. blankSetup();
  1075. return false;
  1076. }
  1077. }
  1078. return true;
  1079. }
  1080. /** Get the current class-specific configuration for this MonPanel.
  1081. * This can be used to capture the current state of the MonPanel so that
  1082. * it can be easily recovered later.
  1083. * @return class-specific configuration information.
  1084. */
  1085. public synchronized
  1086. SavedSetup
  1087. getSetup()
  1088. {
  1089. return itsSetup;
  1090. }
  1091. /** Determine which monitor data server to use and try to establish
  1092. * a connection to it. */
  1093. private
  1094. void
  1095. findServer()
  1096. {
  1097. itsServer = MonClientUtil.getServer();
  1098. }
  1099. /** Get a Panel with all the controls required to configure this provider.
  1100. * @return GUI controls to configure this data provider. */
  1101. public
  1102. MonPanelSetupPanel
  1103. getControls()
  1104. {
  1105. return new LightningSetupPanel(this, itsFrame);
  1106. }
  1107. /** Dump current data to the given output stream. This is the mechanism
  1108. * through which data can be exported to a file.
  1109. * @param p The print stream to write the data to. */
  1110. public synchronized
  1111. void
  1112. export(PrintStream p)
  1113. {
  1114. final String rcsid = "$Id: Lightning.java,v 1.7 2008/02/12 03:01:37 bro764 Exp $";
  1115. p.println("#Dump from Lightning " + rcsid);
  1116. p.println("#Data dumped at "
  1117. + (new AbsTime().toString(AbsTime.Format.UTC_STRING)));
  1118. p.println();
  1119. p.println();
  1120. }
  1121. public String getLabel() { return null; }
  1122. /** Simple test application. */
  1123. public static void main(String[] argv)
  1124. {
  1125. /* JFrame foo = new JFrame("ATTimeSeries Test App");
  1126. foo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  1127. foo.getContentPane().setLayout(new BoxLayout(foo.getContentPane(), BoxLayout.Y_AXIS));
  1128. ATTimeSeries ts1 = new ATTimeSeries();
  1129. SavedSetup s1 = new SavedSetup("ant.temps", "atnf.atoms.mon.gui.monpanel.ATTimeSeries",
  1130. "Antenna Pedestal Temperatures:true:86400000000:0:2:ca05.ant.PEDTEM:ca06.ant.PEDTEM");
  1131. SavedSetup s2 = new SavedSetup("seemon.phases", "atnf.atoms.mon.gui.monpanel.ATTimeSeries",
  1132. "Seeing Monitor Phases:true:86400000000:0:1:seemon.site.seemon.Phase:");
  1133. SavedSetup s3 = new SavedSetup("clock.tickphase", "atnf.atoms.mon.gui.monpanel.ATTimeSeries",
  1134. "Clock Tick Phase:true:86400000000:0:1:caclock.site.clock.TickPhase:");
  1135. ts1.loadSetup(s3);
  1136. foo.getContentPane().add(ts1);
  1137. foo.pack();
  1138. foo.setVisible(true);
  1139. JFrame foo2 = new JFrame("Setup Window");
  1140. foo2.getContentPane().add(ts1.getControls());
  1141. foo2.pack();
  1142. foo2.setVisible(true);
  1143. //ts1.getControls();
  1144. */
  1145. }
  1146. }