commit de7d1d9200a7bca980d8890c85d1ea886ded720b Author: ebner Date: Wed Oct 12 13:53:32 2011 +0200 Initial commit diff --git a/ch.psi.cdump/.classpath b/ch.psi.cdump/.classpath new file mode 100644 index 0000000..8be6238 --- /dev/null +++ b/ch.psi.cdump/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/ch.psi.cdump/.gitignore b/ch.psi.cdump/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/ch.psi.cdump/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ch.psi.cdump/.project b/ch.psi.cdump/.project new file mode 100644 index 0000000..2d212ac --- /dev/null +++ b/ch.psi.cdump/.project @@ -0,0 +1,23 @@ + + + ch.psi.cdump + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/ch.psi.cdump/.settings/org.eclipse.jdt.core.prefs b/ch.psi.cdump/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..37f495c --- /dev/null +++ b/ch.psi.cdump/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,3 @@ +#Wed Oct 12 13:39:19 CEST 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning diff --git a/ch.psi.cdump/.settings/org.eclipse.m2e.core.prefs b/ch.psi.cdump/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..c9a156c --- /dev/null +++ b/ch.psi.cdump/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,5 @@ +#Wed Oct 12 13:36:18 CEST 2011 +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/ch.psi.cdump/pom.xml b/ch.psi.cdump/pom.xml new file mode 100644 index 0000000..dbcce4a --- /dev/null +++ b/ch.psi.cdump/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + ch.psi + cdump + 0.9.6-SNAPSHOT + + + ch.psi + jcae + RELEASE + + + junit + junit + 4.8.2 + test + + + + + i.snapshots + Artifactory Snapshots + http://slsyoke1/artifactory/libs-snapshots-local + + + i.releases + Atrifactory Releases + http://slsyoke1/artifactory/libs-releases-local + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + src/main/assembly/assembly.xml + + + + + + \ No newline at end of file diff --git a/ch.psi.cdump/src/main/assembly/assembly.xml b/ch.psi.cdump/src/main/assembly/assembly.xml new file mode 100644 index 0000000..c9fb787 --- /dev/null +++ b/ch.psi.cdump/src/main/assembly/assembly.xml @@ -0,0 +1,27 @@ + + bin + + + zip + + + + + + lib + false + + + + + + + 0755 + src/main/assembly/bin + bin + + * + + + + \ No newline at end of file diff --git a/ch.psi.cdump/src/main/assembly/bin/cdump b/ch.psi.cdump/src/main/assembly/bin/cdump new file mode 100644 index 0000000..a9bcd31 --- /dev/null +++ b/ch.psi.cdump/src/main/assembly/bin/cdump @@ -0,0 +1,38 @@ +#!/bin/bash + +CURRENTDIR=`pwd` + +# Resolve symlinks +BASEDIR=$0 +while [ -h "$BASEDIR" ]; do + ls=`ls -ld "$BASEDIR"` + link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null` + if expr "$link" : '^/' 2> /dev/null >/dev/null; then + BASEDIR="$link" + else + BASEDIR="`dirname "$BASEDIR"`/$link" + fi +done +BASEDIR=`dirname "$BASEDIR"` + +SCRIPTNAME=`basename ${0}` + +LIB_DIR=`find $BASEDIR/../lib -name "*.jar"` +LIB_DIR=`echo $LIB_DIR | sed -e 's/ /:/g'` + +CLASSPATH=$LIB_DIR + +ARGUMENTS= +VM_ARGUMENTS=-Dch.psi.cdump.home=$BASEDIR/../.. +for i in $@ +do + if [ `expr $i : '-D.*'` != '0' ] ;then + # Extract VM options + VM_ARGUMENTS="$VM_ARGUMENTS $i" + else + ARGUMENTS="$ARGUMENTS $i" + fi +done + +# Execute java +java $VM_ARGUMENTS -Dch.psi.cdump.home=$BASEDIR/../.. -cp $CLASSPATH ch.psi.cdump.CdumpMain $ARGUMENTS \ No newline at end of file diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpAqLogic.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpAqLogic.java new file mode 100644 index 0000000..8fd4fcf --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpAqLogic.java @@ -0,0 +1,106 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Queue; +import java.util.logging.Logger; + +import gov.aps.jca.CAException; +import ch.psi.jcae.ChannelBean; +import ch.psi.jcae.ChannelBeanFactory; + +/** + * Cdump client, creating a monitor on a Waveform channel of an fast ADC and split the data + * for each channel and write it directly to file. + * + * @author ebner + * + */ +public class CdumpAqLogic { + + private enum AdcCmd {READY, GO}; + + // Get Logger + private static final Logger logger = Logger.getLogger(CdumpAqLogic.class.getName()); + + private final String adcChannel; + private final String adcStartStop; + private ChannelBean adcData; + private ChannelBean adcCmd; + private Queue dataQueue; + private PropertyChangeListener listener; + + public CdumpAqLogic(String adcChannel, String adcStartStop, Queue queue){ + this.adcChannel = adcChannel; + this.adcStartStop = adcStartStop; + this.dataQueue = queue; + } + + /** + * Initialize + * @throws InterruptedException + * @throws CAException + */ + public void initialize() throws CAException, InterruptedException{ + adcData = ChannelBeanFactory.getFactory().createChannelBean(int[].class, adcChannel, true); + adcCmd = ChannelBeanFactory.getFactory().createChannelBean(Integer.class, adcStartStop, false); + + // Create listner to + listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + // Append data to processing queue + dataQueue.add((int[]) evt.getNewValue()); + logger.info("Monitor fired"); + } + }; + } + + /** + * Acquire data + * @throws InterruptedException + * @throws CAException + */ + public void acquire() throws CAException, InterruptedException{ + adcCmd.setValue(AdcCmd.GO.ordinal()); + adcData.addPropertyChangeListener(listener); + } + + public void stop() throws CAException, InterruptedException{ + // Detach listener from channel - i.e. stop data acquisition + adcData.removePropertyChangeListener(listener); + adcCmd.setValue(AdcCmd.READY.ordinal()); + dataQueue.add(new int[]{}); + } + + /** + * Clean up used resources + * @throws CAException + */ + public void cleanup() throws CAException{ + // Destroy channel + adcData.destroy(); + adcCmd.destroy(); + } + +} diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpConfiguration.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpConfiguration.java new file mode 100644 index 0000000..9a0ca9e --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpConfiguration.java @@ -0,0 +1,158 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author ebner + * + */ +public class CdumpConfiguration { + + private static final CdumpConfiguration instance = new CdumpConfiguration(); + + private String dataChannel; + private int nelements = 65536; + private String controlChannel; + private String samplingRateChannel; + private String filePrefix = "${yyyy_MM}/${yyyyMMdd}/${yyyyMMddHHmmss}_${name}/${yyyyMMddHHmm}_"; + private String dataDirectory; + + /** + * Singleton - Private constructor + */ + private CdumpConfiguration(){ + loadConfiguration(); + } + + public static CdumpConfiguration getInstance(){ + return instance; + } + + private void loadConfiguration() { + String config = System.getProperty(CdumpService.APP_HOME); + + if(config == null){ + throw new RuntimeException("No configuration file specified via -D"+CdumpService.APP_HOME+"=..."); + } + + Properties properties = new Properties(); + try { + properties.load(new FileReader(config+"/config/cdump.properties")); + } catch (FileNotFoundException e) { + throw new RuntimeException("Configuration file "+config+" not found", e); + } catch (IOException e) { + throw new RuntimeException("Cannot read configuration file "+config, e); + } + + dataChannel = properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".dataChannel", ""); + controlChannel = properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".controlChannel", ""); + samplingRateChannel = properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".samplingRateChannel", ""); + dataDirectory = config+"/data"; + + } + + /** + * @return the dataChannel + */ + public String getDataChannel() { + return dataChannel; + } + /** + * @param dataChannel the dataChannel to set + */ + public void setDataChannel(String dataChannel) { + this.dataChannel = dataChannel; + } + /** + * @return the controlChannel + */ + public String getControlChannel() { + return controlChannel; + } + /** + * @param controlChannel the controlChannel to set + */ + public void setControlChannel(String controlChannel) { + this.controlChannel = controlChannel; + } + /** + * @return the samplingRateChannel + */ + public String getSamplingRateChannel() { + return samplingRateChannel; + } + /** + * @param samplingRateChannel the samplingRateChannel to set + */ + public void setSamplingRateChannel(String samplingRateChannel) { + this.samplingRateChannel = samplingRateChannel; + } + + /** + * @return the nelements + */ + public int getNelements() { + return nelements; + } + + /** + * @return the filePrefix + */ + public String getFilePrefix() { + return filePrefix; + } + + /** + * @return the dataDirectory + */ + public String getDataDirectory() { + return dataDirectory; + } + + public String replaceMacros(String string, Date date, String name){ + String newString = string; + + // Replace scan name macros + newString = newString.replaceAll("\\$\\{name\\}", name); + + + // Replace date macros + Pattern pattern = Pattern.compile("\\$\\{[a-z,A-Z,-,_,:]*\\}"); + Matcher matcher = pattern.matcher(newString); + while(matcher.find()){ + String datePattern = matcher.group(); + datePattern = datePattern.replaceAll("\\$\\{", ""); + datePattern = datePattern.replaceAll("\\}", ""); + SimpleDateFormat datef = new SimpleDateFormat(datePattern); + newString = matcher.replaceFirst(datef.format(date)); + matcher = pattern.matcher(newString); + } + return newString; + } +} diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpMain.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpMain.java new file mode 100644 index 0000000..2ce81b1 --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpMain.java @@ -0,0 +1,119 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump; + +import gov.aps.jca.CAException; + +import java.io.File; +import java.util.Date; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; + +import ch.psi.jcae.ChannelBeanFactory; + +import sun.misc.Signal; +import sun.misc.SignalHandler; + +/** + * @author ebner + * + */ +public class CdumpMain { + + // Get Logger + private static final Logger logger = Logger.getLogger(CdumpMain.class.getName()); + + public static void main(String[] args){ + + + RunConfiguration c = new RunConfiguration(); + + if(args.length != 2){ + System.err.println("Usage: cdump "); + StringBuilder b = new StringBuilder(); + for(String s: RunConfiguration.rates){ + b.append(s); + b.append(" "); + } + System.err.println("Supported rates: "+b.toString()); + System.exit(1); + } + + c.setSamplingRate(args[0]); + + // Calculate data file location/name + String fname = args[1]; + CdumpConfiguration cc = CdumpConfiguration.getInstance(); + String d = cc.getDataDirectory()+"/"+cc.replaceMacros(cc.getFilePrefix(), new Date(), fname)+fname+".txt"; + File f = new File(d); + f.getParentFile().mkdirs(); // Create data base directory + // Set file to save data + logger.info("Set data file to: "+f.getAbsolutePath()); + c.setDatafile(f); + + // Create execution service + final CdumpService service = new CdumpService(); + + + // Stop/abort handling of acquisition + Signal.handle(new Signal("INT"), new SignalHandler() { + /** + * Thread save signal counter + */ + private AtomicInteger signalCount= new AtomicInteger(0); + + /** + * Testing signal handler (in Eclipse) use this after starting scan: + * + * SL5: A=`ps -ef | tail -10 | grep jav[a] | awk '{printf $2}'`;kill -2 $A + * MacOS X: A=`ps -ef | grep AcquisitionMai[n] | awk '{printf $2}'`;kill -2 $A + * + * on the command line use CTRL-C + */ + @Override + public void handle(Signal signal) { + + + int count = signalCount.incrementAndGet(); + + // If signal is received more than 1 time forcefully abort application + if(count>1){ + System.exit(2); + } + + service.stopAcquisition(); + + // Destroy jca context to let the program abort + try { + ChannelBeanFactory.getFactory().getChannelFactory().destroyContext(); + } catch (IllegalStateException e) { + throw new RuntimeException(e); + } catch (CAException e) { + throw new RuntimeException(e); + } + } + }); + + // Take data + service.startAcquisition(c); + + } + +} diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpPrLogic.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpPrLogic.java new file mode 100644 index 0000000..208b420 --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/CdumpPrLogic.java @@ -0,0 +1,119 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.concurrent.BlockingQueue; + +/** + * Processing logic + * @author ebner + * + */ +public class CdumpPrLogic implements Runnable { + + /** + * Data file + */ + private final File file; + private final BlockingQueue dataQueue; + + private final int numberOfElements; + + /** + * + * @param file + * @param dataQueue + * @param nelements Example 65536 + */ + public CdumpPrLogic(File file, BlockingQueue dataQueue, int nelements){ + this.file = file; + this.dataQueue = dataQueue; + this.numberOfElements=nelements; + } + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + int[] value = new int[]{}; + boolean first = true; + int nwaveforms = 0; + + // Open file + PrintWriter w = null; + try { + w = new PrintWriter(new BufferedWriter(new FileWriter(file))); + } catch (IOException e) { + throw new RuntimeException("Cannot open file "+file.getAbsolutePath(), e); + } + + while(true){ + try { + value = dataQueue.take(); + } catch (InterruptedException e) { + // Abort loop + break; + } + + if(value.length==0){ + break; + } + + + if(first){ + int nelements = value.length; + int n = nelements%numberOfElements; + if(n!=0){ + throw new RuntimeException("Array size is not a multiple of 65536"); + } + nwaveforms = nelements/numberOfElements; + + } + + // Split and rotate array/waveform + boolean f = true; + for(int x=0;x. + * + */ + +package ch.psi.cdump; + +import gov.aps.jca.CAException; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.logging.Logger; + +import ch.psi.jcae.ChannelBean; +import ch.psi.jcae.ChannelBeanFactory; + +/** + * @author ebner + * + */ +public class CdumpService { + + public final static String APP_HOME = "ch.psi.cdump.home"; + + + // Get Logger + private static final Logger logger = Logger.getLogger(CdumpService.class.getName()); + + private CdumpAqLogic aqlogic = null; + private CdumpPrLogic prlogic = null; + + /** + * @param args + */ + public void startAcquisition(RunConfiguration c) { + + logger.info("Start acquisition"); + + CdumpConfiguration configuration = CdumpConfiguration.getInstance(); + + try { + + // Set ADC sampling rate + ChannelBean smplRate = ChannelBeanFactory.getFactory().createChannelBean(Integer.class, configuration.getSamplingRateChannel(), false); + smplRate.setValue(c.getSamplingRate()); + smplRate.destroy(); + + BlockingQueue queue = new LinkedBlockingQueue(); + + aqlogic = new CdumpAqLogic(configuration.getDataChannel(), configuration.getControlChannel(), queue); + prlogic = new CdumpPrLogic(c.getDatafile(), queue, configuration.getNelements()); + Thread t = new Thread(prlogic); + + // Initialize acquisition logic + logger.info("Initialize acquisition logic"); + aqlogic.initialize(); + + // Start writer thread + logger.info("Start serialization logic"); + t.start(); + + logger.info("Start acquisition"); + aqlogic.acquire(); + + + } catch (CAException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Stop the data acquisition + */ + public void stopAcquisition(){ + logger.info("Stop acquisition"); + try { + aqlogic.stop(); + aqlogic.cleanup(); + } catch (CAException e) { + throw new RuntimeException(e); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } +} diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/RunConfiguration.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/RunConfiguration.java new file mode 100644 index 0000000..b524910 --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/RunConfiguration.java @@ -0,0 +1,123 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump; + +import java.io.File; + +/** + * @author ebner + * + */ +public class RunConfiguration { + + public final static String[] rates = new String[] {"1Hz","2Hz", "5Hz", "10Hz", "20Hz", "50Hz", "100Hz", "200Hz", "500Hz", + "1kHz", "2kHz", "5kHz", "10kHz", "20kHz", "50kHz", "100kHz"}; + + /** + * 0 = 1Hz + * 1 = 2Hz + * 2 = 5Hz + * 3 = 10Hz + * 4 = 20Hz + * 5 = 50Hz + * 6 = 100Hz + * 7 = 200Hz + * 8 = 500Hz + * 9 = 1000Hz + * 10 = 2000Hz + * 11 = 5000Hz + * 12 = 10000Hz + * 13 = 20000Hz + * 14 = 50000Hz + * 15 = 100000Hz + */ + private int samplingRate = 0; + + /** + * Data file + */ + private File datafile; + + /** + * Time to take data + */ + private Long executionTime = null ; + + /** + * @param samplingRate the samplingRate to set + */ + public void setSamplingRate(int samplingRate) { + this.samplingRate = samplingRate; + } + + /** + * Set sampling rate based on the passed rate string. + * If the string does not match any of the strings specified in the rates variable + * this function will set the rate to 1Hz + * @param rate + */ + public void setSamplingRate(String rate){ + // Default sampling rate 10kHz + setSamplingRate(12); + + for(int i=0;i. + * + */ + +package ch.psi.cdump.ui; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import javax.swing.JLabel; +import javax.swing.ImageIcon; + +/** + * @author ebner + * + */ +public class CalibratePanel extends JPanel { + + /** + * Create the panel. + */ + public CalibratePanel() { + setLayout(new BorderLayout(0, 0)); + + JLabel label = new JLabel(""); + label.setIcon(new ImageIcon(CalibratePanel.class.getResource("/ch/psi/cdump/gui/sine.png"))); + add(label, BorderLayout.CENTER); + + } + +} diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/ui/ControlPanel.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/ui/ControlPanel.java new file mode 100644 index 0000000..a0311a1 --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/ui/ControlPanel.java @@ -0,0 +1,249 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump.ui; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.JTextField; +import javax.swing.JLabel; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.JComboBox; +import javax.swing.JButton; + +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Point; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; + +/** + * @author ebner + * + */ +public class ControlPanel extends JPanel { + private JTextField tfScanName; + private JButton btnCalibrate; + private JComboBox cbSamplingRate; + private JButton btnAcquire; + private JLabel lblRunning; + private JTextField tfMonoFrequency; + private JLabel lblScanName; + private JLabel lblMonoFrequency; + private JLabel lblSamplingRate; + + /** + * Create the panel. + */ + public ControlPanel() { + + tfMonoFrequency = new JTextField(); + tfMonoFrequency.setColumns(10); + + lblMonoFrequency = new JLabel("Mono Frequency [rpm]"); + + JLabel lblFrequency = new JLabel("frequency"); + + cbSamplingRate = new JComboBox(); + + lblSamplingRate = new JLabel("Sampling Rate"); + + tfScanName = new JTextField(); + tfScanName.setColumns(10); + + lblScanName = new JLabel("Scan Name"); + + btnAcquire = new JButton("Acquire"); + btnAcquire.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + if(btnAcquire.getText().equals("Acquire")){ + lblRunning.setVisible(true); + btnAcquire.setText("Stop"); + btnAcquire.requestFocus(); + + // Disable calibrate button + btnCalibrate.setEnabled(false); + cbSamplingRate.setEnabled(false); + lblSamplingRate.setEnabled(false); + lblMonoFrequency.setEnabled(false); + tfMonoFrequency.setEnabled(false); + + tfScanName.setEnabled(false); + lblScanName.setEnabled(false); + + ControlPanel.this.validate(); + + acquire(); + } + else{ + lblRunning.setVisible(false); + btnAcquire.setText("Acquire"); + tfScanName.requestFocus(); + + // Enable calibrate button again + btnCalibrate.setEnabled(true); + cbSamplingRate.setEnabled(true); + lblSamplingRate.setEnabled(true); + lblMonoFrequency.setEnabled(true); + tfMonoFrequency.setEnabled(true); + + tfScanName.setEnabled(true); + lblScanName.setEnabled(true); + + ControlPanel.this.validate(); + + stopAcquire(); + } + } + }); + + lblRunning = new JLabel("[running]"); + lblRunning.setVisible(false); + lblRunning.setFont(new Font("Lucida Grande", Font.BOLD, 13)); + + btnCalibrate = new JButton("Calibrate"); + btnCalibrate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + if(btnCalibrate.getText().equals("Calibrate")){ + + btnCalibrate.setText("Stop"); + btnCalibrate.requestFocus(); + + // Disable acquire components + tfScanName.setEnabled(false); + lblScanName.setEnabled(false); + btnAcquire.setEnabled(false); + lblRunning.setEnabled(false); + + ControlPanel.this.validate(); + + calibrate(); + } + else{ + + btnCalibrate.setText("Calibrate"); + tfScanName.requestFocus(); + + // Enable acquire components + tfScanName.setEnabled(true); + lblScanName.setEnabled(true); + btnAcquire.setEnabled(true); + lblRunning.setEnabled(true); + + ControlPanel.this.validate(); + + stopCalibrate(); + } + } + }); + GroupLayout groupLayout = new GroupLayout(this); + groupLayout.setHorizontalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addContainerGap() + .addGroup(groupLayout.createParallelGroup(Alignment.LEADING, false) + .addGroup(groupLayout.createSequentialGroup() + .addComponent(btnAcquire, GroupLayout.PREFERRED_SIZE, 113, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(lblRunning)) + .addGroup(groupLayout.createSequentialGroup() + .addComponent(tfMonoFrequency, 113, 113, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(lblMonoFrequency) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(lblFrequency) + .addGap(29)) + .addGroup(groupLayout.createSequentialGroup() + .addGroup(groupLayout.createParallelGroup(Alignment.TRAILING, false) + .addComponent(cbSamplingRate, Alignment.LEADING, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnCalibrate, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(tfScanName, 113, 113, Short.MAX_VALUE)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.LEADING) + .addComponent(lblSamplingRate) + .addComponent(lblScanName)) + .addGap(148))) + .addContainerGap(38, Short.MAX_VALUE)) + ); + groupLayout.setVerticalGroup( + groupLayout.createParallelGroup(Alignment.LEADING) + .addGroup(groupLayout.createSequentialGroup() + .addContainerGap() + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(tfMonoFrequency, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(lblMonoFrequency) + .addComponent(lblFrequency)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(cbSamplingRate, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(lblSamplingRate)) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(btnCalibrate) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(tfScanName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(lblScanName)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE) + .addComponent(btnAcquire) + .addComponent(lblRunning)) + .addContainerGap(131, Short.MAX_VALUE)) + ); + setLayout(groupLayout); + } + + private void acquire(){ + } + + private void stopAcquire() { + } + + private JFrame calibratePlot = null; + + private void calibrate(){ + + Point p = this.getLocationOnScreen(); + + Point p1 = new Point(p.getLocation().x+this.getWidth(), p.getLocation().y); + + final JFrame frame = new JFrame(); + frame.setLocation(p1); + frame.add(new CalibratePanel()); + + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + frame.setUndecorated(true); + frame.pack(); + + calibratePlot = frame; + + EventQueue.invokeLater(new Runnable() { + public void run() { + frame.setVisible(true); + } + }); + } + + private void stopCalibrate(){ + if(calibratePlot!=null){ + calibratePlot.dispose(); + } + } +} diff --git a/ch.psi.cdump/src/main/java/ch/psi/cdump/ui/MainGui.java b/ch.psi.cdump/src/main/java/ch/psi/cdump/ui/MainGui.java new file mode 100644 index 0000000..a981c1d --- /dev/null +++ b/ch.psi.cdump/src/main/java/ch/psi/cdump/ui/MainGui.java @@ -0,0 +1,50 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump.ui; + +import java.awt.EventQueue; + +import javax.swing.JFrame; + +/** + * @author ebner + * + */ +public class MainGui { + + /** + * @param args + */ + public static void main(String[] args) { + // TODO Auto-generated method stub + final JFrame frame = new JFrame(); + frame.add(new ControlPanel()); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + + EventQueue.invokeLater(new Runnable() { + public void run() { + frame.setVisible(true); + } + }); + } + +} diff --git a/ch.psi.cdump/src/main/resources/.gitignore b/ch.psi.cdump/src/main/resources/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/ch.psi.cdump/src/test/java/ch/psi/cdump/CdumpPrLogicTest.java b/ch.psi.cdump/src/test/java/ch/psi/cdump/CdumpPrLogicTest.java new file mode 100644 index 0000000..d780512 --- /dev/null +++ b/ch.psi.cdump/src/test/java/ch/psi/cdump/CdumpPrLogicTest.java @@ -0,0 +1,64 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This code is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * merchantability or fitness for a particular purpose. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.cdump; + +import java.io.File; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @author ebner + * + */ +public class CdumpPrLogicTest { + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + } + + /** + * Test method for {@link ch.psi.cdump.CdumpPrLogic#run()}. + */ + @Test + public void testRun() { + BlockingQueue queue = new LinkedBlockingQueue(); + queue.add(new int[] {1,2,3,4,11,12,13,14}); + queue.add(new int[] {5,6,7,8,15,16,17,18}); + queue.add(new int[]{}); + CdumpPrLogic logic = new CdumpPrLogic(new File("test.txt"), queue, 4); + + logic.run(); + } + +} diff --git a/ch.psi.cdump/src/test/resources/.gitignore b/ch.psi.cdump/src/test/resources/.gitignore new file mode 100644 index 0000000..e69de29