BodePlotter.java
/*
* Created on 2007/03/30
* Copyright (C) 2007 Koga Laboratory. All rights reserved.
*
*/
package org.mklab.tool.control;
import java.util.ArrayList;
import java.util.List;
import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.tool.graph.gnuplot.Canvas;
import org.mklab.tool.graph.gnuplot.Gnuplot;
/**
* ボード線図を描画するクラスです。
*
* @author koga
* @version $Revision: 1.7 $, 2007/03/30
*/
public class BodePlotter extends Plotter {
/** Gnuplot */
private Gnuplot gnuplot;
/** ゲイン線図のキャンバス */
private Canvas gainGraph;
/** 位相線図のキャンバス */
private Canvas phaseGraph;
/** ゲインデータ */
private DoubleMatrix gains;
/** 位相データ */
private DoubleMatrix phases;
/** 評価する周波数 */
private DoubleMatrix w;
/**
* 新しく生成された<code>BodePlotter</code>オブジェクトを初期化します。
*
* @param gnuplot Gnuplot
*/
public BodePlotter(final Gnuplot gnuplot) {
this.gnuplot = gnuplot;
this.gnuplot.createCanvas(2, 1);
this.gainGraph = this.gnuplot.getCanvas(0, 0);
this.phaseGraph = this.gnuplot.getCanvas(1, 0);
}
/**
* ゲイン線図と位相線図を描画します。
*
* @param magnitudePhaseList 大きさと位相のリスト
* @param angularFrequencies 評価する周波数
*/
public void plot(final List<List<DoubleMatrix>> magnitudePhaseList, final DoubleMatrix angularFrequencies) {
final List<DoubleMatrix> magnitudes = new ArrayList<>();
for (final List<DoubleMatrix> magnitudePhase : magnitudePhaseList) {
final DoubleMatrix magnitudeColumn = magnitudePhase.get(0);
magnitudes.add(magnitudeColumn);
}
if (this.gainGraph.isKeepingLineProperties() == false) {
setupLineNameAndType(magnitudes);
}
setupGainPhase(magnitudePhaseList, angularFrequencies);
plotGain();
plotPhase();
if (this.gainGraph.isKeepingLineProperties() == false) {
initializeLineTypes();
}
}
/**
* ゲインデータと位相データを設定します。
*
* @param magnitudesPhases 大きさと位相のリスト
* @param angularFrequencies 評価する周波数
*/
private void setupGainPhase(final List<List<DoubleMatrix>> magnitudesPhases, final DoubleMatrix angularFrequencies) {
DoubleMatrix localGains = new DoubleMatrix(0, angularFrequencies.length());
DoubleMatrix localPhases = new DoubleMatrix(0, angularFrequencies.length());
for (final List<DoubleMatrix> magnitudePhase : magnitudesPhases) {
final DoubleMatrix magnitudeColumn = magnitudePhase.get(0);
final DoubleMatrix phaseColumn = magnitudePhase.get(1);
for (int outputNumber = 1; outputNumber <= magnitudeColumn.getRowSize(); outputNumber++) {
final DoubleMatrix magnitude = magnitudeColumn.getRowVector(outputNumber);
final DoubleMatrix phase = phaseColumn.getRowVector(outputNumber);
if (magnitude.isZero()) {
continue;
}
localGains = localGains.appendDown(magnitude.log10ElementWise().multiply(20));
localPhases = localPhases.appendDown(phase);
}
}
this.w = angularFrequencies;
this.gains = localGains;
this.phases = localPhases;
}
/**
* ゲイン線図を描画します。
*/
private void plotGain() {
final double frequencyGridInterval = 10;
final double frequencyMin = Math.pow(10, Math.floor(Math.log10(this.w.min().doubleValue())));
final double frequencyMax = Math.pow(10, Math.ceil(Math.log10(this.w.max().doubleValue())));
double gainGridInterval = Math.ceil(Math.ceil((this.gains.max().doubleValue() - this.gains.min().doubleValue()) / 20) / 6) * 20;
gainGridInterval = Math.max(gainGridInterval, 10);
double gainMin = Math.floor(this.gains.min().doubleValue() / gainGridInterval) * gainGridInterval;
double gainMax = Math.ceil(this.gains.max().doubleValue() / gainGridInterval) * gainGridInterval;
if (Math.abs(gainMax - gainMin) <= gainGridInterval) {
if (Math.abs(gainMax) < 1) {
gainMax = 20;
gainMin = -40;
} else {
if (gainMax < 0) {
gainMax = 0;
gainMin = gainMin - 20;
} else {
gainMax = gainMax + 20;
gainMin = 0;
}
}
gainGridInterval = Math.ceil(Math.ceil((gainMax - gainMin) / 20) / 6) * 20;
}
this.gainGraph.setYLabel("[dB]", -1.5, 4.0); //$NON-NLS-1$
this.gainGraph.setGridVisible(true);
this.gainGraph.setLeftMargin(10);
this.gainGraph.setXRange(frequencyMin, frequencyMax);
this.gainGraph.setXTics(frequencyMin, frequencyGridInterval, frequencyMax);
this.gainGraph.setYRange(gainMin, gainMax);
this.gainGraph.setYTics(gainMin, gainGridInterval, gainMax);
this.gainGraph.semilogx(this.w, this.gains, this.lineNames.values().toArray(new String[this.lineNames.size()]));
}
/**
* 位相線図を描画します。
*/
private void plotPhase() {
final double frequencyGridInterval = 10;
final double frequencyMin = Math.pow(10, Math.floor(Math.log10(this.w.min().doubleValue())));
final double frequencyMax = Math.pow(10, Math.ceil(Math.log10(this.w.max().doubleValue())));
double phaseGridInterval = Math.ceil(Math.ceil((this.phases.max().doubleValue() - this.phases.min().doubleValue()) / 30) / 6) * 30;
phaseGridInterval = Math.max(phaseGridInterval, 10);
double phaseMin = Math.floor(this.phases.min().doubleValue() / phaseGridInterval) * phaseGridInterval;
double phaseMax = Math.ceil(this.phases.max().doubleValue() / phaseGridInterval) * phaseGridInterval;
if (Math.abs(phaseMax - phaseMin) <= phaseGridInterval) {
if (Math.abs(phaseMax) < 1) {
phaseMax = 90;
phaseMin = -90;
} else {
if (phaseMax < 0) {
phaseMax = 0;
phaseMin = phaseMin - 90;
} else {
phaseMax = phaseMax + 90;
phaseMin = 0;
}
}
phaseGridInterval = Math.ceil(Math.ceil((phaseMax - phaseMin) / 30) / 6) * 30;
}
this.phaseGraph.setYLabel("[deg]", -1.5, 3.5); //$NON-NLS-1$
this.phaseGraph.setGridVisible(true);
this.phaseGraph.setLeftMargin(10);
this.phaseGraph.setXRange(frequencyMin, frequencyMax);
this.phaseGraph.setXTics(frequencyMin, frequencyGridInterval, frequencyMax);
this.phaseGraph.setYRange(phaseMin, phaseMax);
this.phaseGraph.setYTics(phaseMin, phaseGridInterval, phaseMax);
this.phaseGraph.semilogx(this.w, this.phases, this.lineNames.values().toArray(new String[this.lineNames.size()]));
}
/**
* @see org.mklab.tool.control.Plotter#setGraphLineWidth(int, int)
*/
@Override
public void setGraphLineWidth(final int lineNumber, final int width) {
if (this.gainGraph != null) {
this.gainGraph.setLineWidth(lineNumber, width);
}
if (this.phaseGraph != null) {
this.phaseGraph.setLineWidth(lineNumber, width);
}
}
/**
* @see org.mklab.tool.control.Plotter#getGraphLineWidth(int)
*/
@Override
public int getGraphLineWidth(final int lineNumber) {
return this.gainGraph.getLineWidth(lineNumber);
}
/**
* @see org.mklab.tool.control.Plotter#setGraphLineType(int, int)
*/
@Override
public void setGraphLineType(final int lineNumber, final int type) {
if (this.gainGraph != null) {
this.gainGraph.setLineType(lineNumber, type);
}
if (this.phaseGraph != null) {
this.phaseGraph.setLineType(lineNumber, type);
}
}
/**
* @see org.mklab.tool.control.Plotter#getGraphLineType(int)
*/
@Override
public int getGraphLineType(final int lineNumber) {
return this.gainGraph.getLineType(lineNumber);
}
/**
* @see org.mklab.tool.control.Plotter#setGraphLineVisible(int, boolean)
*/
@Override
public void setGraphLineVisible(final int lineNumber, final boolean visible) {
if (this.gainGraph != null) {
this.gainGraph.setLineVisible(lineNumber, visible);
}
if (this.phaseGraph != null) {
this.phaseGraph.setLineVisible(lineNumber, visible);
}
}
/**
* @see org.mklab.tool.control.Plotter#isGraphLineVisible(int)
*/
@Override
public boolean isGraphLineVisible(final int lineNumber) {
return this.gainGraph.isLineVisible(lineNumber);
}
/**
* @see org.mklab.tool.control.Plotter#setGraphLineName(int, java.lang.String)
*/
@Override
public void setGraphLineName(final int lineNumber, final String name) {
if (this.gainGraph != null) {
this.gainGraph.setLineName(lineNumber, name);
}
if (this.phaseGraph != null) {
this.phaseGraph.setLineName(lineNumber, name);
}
}
/**
* @see org.mklab.tool.control.Plotter#getGraphLineName(int)
*/
@Override
public String getGraphLineName(final int lineNumber) {
return this.gainGraph.getLineName(lineNumber);
}
/**
* @see org.mklab.tool.control.Plotter#setGraphFontSize(int)
*/
@Override
public void setGraphFontSize(final int fontSize) {
if (this.gainGraph != null) {
this.gainGraph.setFontSize(fontSize);
}
if (this.phaseGraph != null) {
this.phaseGraph.setFontSize(fontSize);
}
}
/**
* @see org.mklab.tool.control.Plotter#getGraphFontSize()
*/
@Override
public int getGraphFontSize() {
return this.gainGraph.getFontSize();
}
/**
* 線のプロパティを保存するか設定します。
*
* @param keepingLineProperties 線のプロパティを保存するならばtrue、そうでなければfalse
*/
public void setKeepingLineProperties(final boolean keepingLineProperties) {
this.gainGraph.setKeepingLineProperties(keepingLineProperties);
this.phaseGraph.setKeepingLineProperties(keepingLineProperties);
}
}