/** * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * All rights reserved. This program and the accompanying materials are made available under * the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html. * */ package gov.redhawk.ui.port.nxmplot; import gov.redhawk.internal.ui.port.nxmplot.PlotSession; import gov.redhawk.ui.port.nxmblocks.FftNxmBlockSettings; import gov.redhawk.ui.port.nxmplot.PlotSettings.PlotMode; import gov.redhawk.ui.port.nxmplot.preferences.PlotPreferences; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import nxm.sys.lib.Data; import org.eclipse.jdt.annotation.NonNull; /** * @since 3.0 */ public final class NxmPlotUtil { /** key to get NeXtMidas Command ID entry in Map returned from launchInputMacro(..) methods. */ private static final String KEY_COMMAND = "command"; /** key to get NeXtMidas Pipe/File name entry in Map returned from launchInputMacro(..) methods. */ private static final String KEY_FILE = "file"; private static final String EMPTY_STRING = ""; private static final int MAX_RMIF_PACKET_SIZE = 32768; // in bytes private NxmPlotUtil() { } /** * Get default pipe qualifiers for specified plot type. * @since 4.2 */ public static String getDefaultPlotQualifiers(PlotType type) { if (type == null) { return null; } switch (type) { case RASTER: return null; default: return "{CL=8}"; // <-- quick data thinning for line plots by skipping (n-1) elements for every 1 element read (for TL=1) } } /** * @since 4.2 */ public static String getDefaultPlotArgs(PlotType type) { if (type == null) { return null; } switch (type) { case RASTER: return "TYPE=RASTER View=iYX SCALE=AutoMin|AutoMax|NoAverage AUTOL=16"; case CONTOUR: // fall-through case DOT: // fall-through case MESH: // fall-through case LINE: // fall-through case POINT: return "TYPE=" + type + " AXIS=+GRID OPTIONS=BStore SCALE=AutoMin|AutoMax|NoAverage AUTOL=16"; default: return null; } } /** * @since 4.2 */ public static String getDefaultPlotSwitches(PlotType type) { if (type == null) { return null; } switch (type) { case RASTER: return "/LPS=200/RT/NICE/FOCUS=FALSE"; case CONTOUR: // fall-through case DOT: // fall-through case MESH: // fall-through case LINE: // fall-through case POINT: return "/RT/NICE/FOCUS=FALSE"; default: return null; } } /** * @param plotSettings merge desired plot settings with default plot arguments * @return never null, an empty string if plotSettings is null, * otherwise the default plot args for the specified plotSettings. * @since 4.4 */ @NonNull public static String getDefaultPlotArgs(PlotSettings plotSettings) { if (plotSettings == null) { return NxmPlotUtil.EMPTY_STRING; } PlotType plotType = plotSettings.getPlotType(); String plotArgs = NxmPlotUtil.getDefaultPlotArgs(plotType); if (plotArgs == null) { plotArgs = NxmPlotUtil.EMPTY_STRING; // so we can easily append to plot args below } PlotMode plotMode = plotSettings.getPlotMode(); if (plotMode != null) { plotArgs += " CM=" + plotSettings.getPlotMode().toModeString(); } // user specified launch arguments could override any of the previous settings if (plotSettings.getLaunchArgs() != null) { plotArgs += " " + plotSettings.getLaunchArgs(); } return plotArgs; } /** * @param plotSettings merge desired plot settings with default plot switches * @return never null, an empty string if plotSettings is null or unknown plot type, * otherwise the default plot switches for the specified plotSettings. * @since 4.4 */ @NonNull public static String getDefaultPlotSwitches(PlotSettings plotSettings) { if (plotSettings == null) { return NxmPlotUtil.EMPTY_STRING; } PlotType plotType = plotSettings.getPlotType(); String plotSwitches = NxmPlotUtil.getDefaultPlotSwitches(plotType); if (plotSwitches == null) { plotSwitches = NxmPlotUtil.EMPTY_STRING; // so we can easily append to plot args below } Boolean enablePlotMenu = plotSettings.getEnablePlotMenu(); if (enablePlotMenu == null) { // not set, get user's configured workbench preference for this enablePlotMenu = PlotPreferences.ENABLE_CONFIGURE_MENU_USING_MOUSE.getValue(PlotActivator.getDefault().getPreferenceStore()); plotSettings.setEnablePlotMenu(enablePlotMenu); } if (Boolean.FALSE.equals(enablePlotMenu)) { // PLOT has configure menu on by default plotSwitches += "/EVENTFILTER=+NoMiddleMouse"; // so only need to disable when false } // user specified launch switches could override any of the previous settings if (plotSettings.getLaunchSwitches() != null) { plotSwitches += plotSettings.getLaunchSwitches(); } return plotSwitches; } public static String formatPlotArgs(Map<String, String> args) { StringBuilder sb = new StringBuilder(); String delim = ""; for (Entry<String, String> entry : args.entrySet()) { String valueString = null; if (entry.getValue() == null || "".equals(entry.getValue())) { valueString = ""; } else { valueString = "=" + entry.getValue(); } sb.append(delim + entry.getKey() + valueString); delim = " "; } return sb.toString(); } public static String formatPlotSwitches(Map<String, String> switches) { StringBuilder sb = new StringBuilder(); for (Entry<String, String> entry : switches.entrySet()) { sb.append("/" + entry.getKey() + "=" + entry.getValue()); } return sb.toString(); } public static String formatPlotQualifiers(Map<String, String> qualifiers) { StringBuilder sb = new StringBuilder(); sb.append("{"); String delim = ""; for (Entry<String, String> entry : qualifiers.entrySet()) { sb.append(delim + entry.getKey() + "=" + entry.getValue()); delim = ","; } sb.append("}"); return sb.toString(); } private static Map<String, String> launchInputMacro(final SddsSource sdds, final Integer magExponent, final FftNxmBlockSettings fft, final AbstractNxmPlotWidget plotWidget, String pipeSize) { final String outName = AbstractNxmPlotWidget.createUniqueName(true); final String transformIn = AbstractNxmPlotWidget.createUniqueName(true); final String fftIn = AbstractNxmPlotWidget.createUniqueName(true); plotWidget.runHeadlessCommand("PIPE ON"); final StringBuilder command = new StringBuilder(); final String sourcenicId = "SOURCENIC_" + AbstractNxmPlotWidget.createUniqueName(false); if (pipeSize == null) { // Default size pipeSize = "128k"; } command.append("SOURCENIC/PS=" + pipeSize + "/ID=" + sourcenicId); command.append("/fc=" + sdds.format); if (sdds.mcastAddress != null) { command.append("/mgrp=" + sdds.mcastAddress); } if (sdds.vlan != 0) { command.append("/vlan=" + sdds.vlan); } if (sdds.port != 0) { command.append("/port=" + sdds.port); } if (magExponent != null) { command.append(" out=" + transformIn); plotWidget.runHeadlessCommand(command.toString()); command.delete(0, command.length()); command.append("FCALCULATOR "); if (fft == null) { command.append(outName + " "); command.append(transformIn + " "); command.append(magExponent + " pow"); plotWidget.runHeadlessCommand(command.toString()); } else { command.append(fftIn + " "); command.append(transformIn + " "); command.append(magExponent + " pow"); plotWidget.runHeadlessCommand(command.toString()); command.delete(0, command.length()); command.append("fft/id=" + "\"FFT_" + AbstractNxmPlotWidget.createUniqueName(false) + "\"" + "/psd/ac"); command.append(" in1=\"" + fftIn + "\""); command.append(" out1=\"" + outName + "\""); command.append(" nfft=" + fft.getTransformSize() + " win=\"" + fft.getWindow() + "\" over=" + fft.getOverlap() + " navg=" + fft.getNumAverages()); plotWidget.runHeadlessCommand(command.toString()); } } else { if (fft == null) { command.append(" out=" + outName); plotWidget.runHeadlessCommand(command.toString()); } else { command.append(" out=" + fftIn); plotWidget.runHeadlessCommand(command.toString()); command.delete(0, command.length()); command.append("fft/id=" + "\"FFT_" + AbstractNxmPlotWidget.createUniqueName(false) + "\"" + "/psd/ac"); command.append(" in1=\"" + fftIn + "\""); command.append(" out1=\"" + outName + "\""); command.append(" nfft=" + fft.getTransformSize() + " win=\"" + fft.getWindow() + "\" over=" + fft.getOverlap() + " navg=" + fft.getNumAverages()); plotWidget.runHeadlessCommand(command.toString()); } } plotWidget.runHeadlessCommand("PIPE RUN"); Map<String, String> map = new HashMap<String, String>(); map.put(NxmPlotUtil.KEY_COMMAND, sourcenicId); map.put(NxmPlotUtil.KEY_FILE, outName); return map; } private static Map<String, String> launchInputMacro(final File file, String format, final boolean thinData, Integer thinIncr, Integer yDelta, final AbstractNxmPlotWidget plotWidget) { final String outName = AbstractNxmPlotWidget.createUniqueName(true); final String thinIn = AbstractNxmPlotWidget.createUniqueName(true); format = format.toUpperCase(); int bytesPerSample = Data.getBPA(format); // since 4.2 if (yDelta == null || yDelta.intValue() == 0) { yDelta = Integer.valueOf(5); } if (thinIncr == null || thinIncr.intValue() == 0) { // make the resulting file 32k bytes in size, to conform to RMIF packet size limit thinIncr = new Double(Math.floor(file.length() / (double) NxmPlotUtil.MAX_RMIF_PACKET_SIZE / bytesPerSample)).intValue(); } plotWidget.runHeadlessCommand("PIPE ON"); if (thinData) { plotWidget.runHeadlessCommand("NOOP/WRAP/RT " + file.getAbsolutePath() + "{ydelta=" + yDelta.intValue() + ",yu=time} " + thinIn); plotWidget.runHeadlessCommand("THIN IN=" + thinIn + " OUT=" + outName + " FINC=" + thinIncr.intValue()); } else { plotWidget.runHeadlessCommand("NOOP/WRAP/RT " + file.getAbsolutePath() + "{ydelta=" + yDelta.intValue() + ",yu=time} " + outName); } plotWidget.runHeadlessCommand("PIPE RUN"); Map<String, String> map = new HashMap<String, String>(); map.put(NxmPlotUtil.KEY_FILE, outName); return map; } public static IPlotSession addSource(final SddsSource sdds, final AbstractNxmPlotWidget plotWidget, final String qualifers) { return NxmPlotUtil.addSource(sdds, null, null, plotWidget, qualifers); } /** * @since 4.4 */ public static IPlotSession addSource(final SddsSource sdds, final FftNxmBlockSettings fft, final AbstractNxmPlotWidget plotWidget, final String qualifers) { return NxmPlotUtil.addSource(sdds, null, fft, plotWidget, qualifers); } /** * @since 4.4 */ public static IPlotSession addSource(final SddsSource sdds, final Integer magExponent, final FftNxmBlockSettings fft, final AbstractNxmPlotWidget plotWidget, final String qualifiers) { final Map<String, String> outputIds = NxmPlotUtil.launchInputMacro(sdds, magExponent, fft, plotWidget, null); PlotSession session = new PlotSession(plotWidget, outputIds.get(NxmPlotUtil.KEY_COMMAND), outputIds.get(NxmPlotUtil.KEY_FILE)); plotWidget.addSource(session.getSourceId(), ((qualifiers == null) ? "" : qualifiers), session); return session; } public static void setPlotToReal(boolean real, AbstractNxmPlotWidget nxmPlotWidget) { if (real) { nxmPlotWidget.configurePlot(Collections.singletonMap("MODE", "MAG")); } else { nxmPlotWidget.configurePlot(Collections.singletonMap("MODE", "REAL")); } } /** * @since 4.2 */ public static IPlotSession addSource(final File file, String format, final boolean thinData, Integer thinIncr, Integer yDelta, final AbstractNxmPlotWidget plotWidget, final String qualifiers) { final Map<String, String> outputIds = NxmPlotUtil.launchInputMacro(file, format, thinData, thinIncr, yDelta, plotWidget); PlotSession session = new PlotSession(plotWidget, outputIds.get(NxmPlotUtil.KEY_COMMAND), outputIds.get(NxmPlotUtil.KEY_FILE)); plotWidget.addSource(session.getSourceId(), ((qualifiers == null) ? "" : qualifiers), session); return session; } }