public boolean play() { try { if (playState != STOPPED) playStop(); if (audioBytes == null) return false; DataLine.Info info = new DataLine.Info(Clip.class, format); clip = (Clip) AudioSystem.getLine(info); clip.addLineListener(new ClipListener()); long clipStart = (long) (audioBytes.length * getStartTime() / (getDuration() * 1000.0)); long clipEnd = (long) (audioBytes.length * getEndTime() / (getDuration() * 1000.0)); if ((clipEnd - clipStart) > MAX_CLIP_LENGTH) clipEnd = clipStart + MAX_CLIP_LENGTH; byte[] clipBytes = new byte[(int) (clipEnd - clipStart)]; System.arraycopy(audioBytes, (int) clipStart, clipBytes, 0, clipBytes.length); clip.open(format, clipBytes, 0, clipBytes.length); FloatControl panControl = (FloatControl) clip.getControl(FloatControl.Type.PAN); panControl.setValue((float) panSetting / 100.0f); double value = (double) gainSetting; FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); float dB = (float) (Math.log(value == 0.0 ? 0.0001 : value) / Math.log(10.0) * 20.0); gainControl.setValue(dB); double playStartTime = (player.getSeekTime() / 100) * (playGetLength()); clip.setMicrosecondPosition((long) playStartTime); clip.start(); playState = PLAYING; return true; } catch (Exception ex) { ex.printStackTrace(); playState = STOPPED; clip = null; return false; } }
public double getValue(DatanVector x) { double result; double a = sqrt2pi * x.getElement(1); if (a < small) f = big; else f = Math.log(a); result = (double) y.length * f; for (int i = 0; i < y.length; i++) { f = Math.pow((y[i] - x.getElement(0)), 2.) / (2. * x.getElement(1) * x.getElement(1)); result += f; } return result; }
private int percentToZoomLevel(double percent) { double minZoomPercent = mImagePresentationModel.getMinZoom(); double zoomIncrement = computeZoomIncrementToMakeExactlyNIncrements(); return (int) Math.round((Math.log(percent / minZoomPercent) / Math.log(zoomIncrement)) + 1); }
/** Translation durchfuehren */ public void process() { int i, j, k; int ch, len; float f1; double d1, d2, d3, d4, d5; long progOff, progLen, lo; // io AudioFile reInF = null; AudioFile imInF = null; AudioFile reOutF = null; AudioFile imOutF = null; AudioFileDescr reInStream = null; AudioFileDescr imInStream = null; AudioFileDescr reOutStream = null; AudioFileDescr imOutStream = null; FloatFile reFloatF[] = null; FloatFile imFloatF[] = null; File reTempFile[] = null; File imTempFile[] = null; int outChanNum; float[][] reInBuf; // [ch][i] float[][] imInBuf; // [ch][i] float[][] reOutBuf = null; // [ch][i] float[][] imOutBuf = null; // [ch][i] float[] convBuf1, convBuf2; boolean complex; PathField ggOutput; // Synthesize Param ampRef = new Param(1.0, Param.ABS_AMP); // transform-Referenz float gain; // gain abs amp float dryGain, wetGain; float inGain; float maxAmp = 0.0f; Param peakGain; int inLength, inOff; int pre; int post; int length; int framesRead, framesWritten, outLength; boolean polarIn, polarOut; // phase unwrapping double[] phi; int[] wrap; double[] carry; Param lenRef; topLevel: try { complex = pr.bool[PR_HASIMINPUT] || pr.bool[PR_HASIMOUTPUT]; polarIn = pr.intg[PR_OPERATOR] == OP_POLAR2RECT; polarOut = pr.intg[PR_OPERATOR] == OP_RECT2POLAR; if ((polarIn || polarOut) && !complex) throw new IOException(ERR_NOTCOMPLEX); // ---- open input ---- reInF = AudioFile.openAsRead(new File(pr.text[PR_REINPUTFILE])); reInStream = reInF.getDescr(); inLength = (int) reInStream.length; reInBuf = new float[reInStream.channels][8192]; imInBuf = new float[reInStream.channels][8192]; if (pr.bool[PR_HASIMINPUT]) { imInF = AudioFile.openAsRead(new File(pr.text[PR_IMINPUTFILE])); imInStream = imInF.getDescr(); if (imInStream.channels != reInStream.channels) throw new IOException(ERR_COMPLEX); inLength = (int) Math.min(inLength, imInStream.length); } lenRef = new Param(AudioFileDescr.samplesToMillis(reInStream, inLength), Param.ABS_MS); d1 = AudioFileDescr.millisToSamples( reInStream, (Param.transform(pr.para[PR_OFFSET], Param.ABS_MS, lenRef, null).value)); j = (int) (d1 >= 0.0 ? (d1 + 0.5) : (d1 - 0.5)); // correct rounding for negative values! length = (int) (AudioFileDescr.millisToSamples( reInStream, (Param.transform(pr.para[PR_LENGTH], Param.ABS_MS, lenRef, null)).value) + 0.5); // System.err.println( "offset = "+j ); if (j >= 0) { inOff = Math.min(j, inLength); if (!pr.bool[PR_REVERSE]) { reInF.seekFrame(inOff); if (pr.bool[PR_HASIMINPUT]) { imInF.seekFrame(inOff); } } inLength -= inOff; pre = 0; } else { inOff = 0; pre = Math.min(-j, length); } inLength = Math.min(inLength, length - pre); post = length - pre - inLength; if (pr.bool[PR_REVERSE]) { i = pre; pre = post; post = i; inOff += inLength; } // .... check running .... if (!threadRunning) break topLevel; // for( op = 0; op < 2; op++ ) { // System.out.println( op +": pre "+pre[op]+" / len "+inLength[op]+" / post "+post[op] ); // } // System.out.println( "tot "+length[0]); outLength = length; outChanNum = reInStream.channels; // ---- open output ---- ggOutput = (PathField) gui.getItemObj(GG_REOUTPUTFILE); if (ggOutput == null) throw new IOException(ERR_MISSINGPROP); reOutStream = new AudioFileDescr(reInStream); ggOutput.fillStream(reOutStream); reOutStream.channels = outChanNum; // well, more sophisticated code would // move and truncate the markers... if ((pre == 0) /* && (post == 0) */) { reInF.readMarkers(); reOutStream.setProperty( AudioFileDescr.KEY_MARKERS, reInStream.getProperty(AudioFileDescr.KEY_MARKERS)); } reOutF = AudioFile.openAsWrite(reOutStream); reOutBuf = new float[outChanNum][8192]; imOutBuf = new float[outChanNum][8192]; if (pr.bool[PR_HASIMOUTPUT]) { imOutStream = new AudioFileDescr(reInStream); ggOutput.fillStream(imOutStream); imOutStream.channels = outChanNum; imOutStream.file = new File(pr.text[PR_IMOUTPUTFILE]); imOutF = AudioFile.openAsWrite(imOutStream); } // .... check running .... if (!threadRunning) break topLevel; // ---- Further inits ---- phi = new double[outChanNum]; wrap = new int[outChanNum]; carry = new double[outChanNum]; for (ch = 0; ch < outChanNum; ch++) { phi[ch] = 0.0; wrap[ch] = 0; carry[ch] = Double.NEGATIVE_INFINITY; } progOff = 0; // read, transform, write progLen = (long) outLength * 3; wetGain = (float) (Param.transform(pr.para[PR_WETMIX], Param.ABS_AMP, ampRef, null)).value; dryGain = (float) (Param.transform(pr.para[PR_DRYMIX], Param.ABS_AMP, ampRef, null)).value; if (pr.bool[PR_DRYINVERT]) { dryGain = -dryGain; } inGain = (float) (Param.transform(pr.para[PR_INPUTGAIN], Param.ABS_AMP, ampRef, null)).value; if (pr.bool[PR_INVERT]) { inGain = -inGain; } // normalization requires temp files if (pr.intg[PR_GAINTYPE] == GAIN_UNITY) { reTempFile = new File[outChanNum]; reFloatF = new FloatFile[outChanNum]; for (ch = 0; ch < outChanNum; ch++) { // first zero them because an exception might be thrown reTempFile[ch] = null; reFloatF[ch] = null; } for (ch = 0; ch < outChanNum; ch++) { reTempFile[ch] = IOUtil.createTempFile(); reFloatF[ch] = new FloatFile(reTempFile[ch], GenericFile.MODE_OUTPUT); } if (pr.bool[PR_HASIMOUTPUT]) { imTempFile = new File[outChanNum]; imFloatF = new FloatFile[outChanNum]; for (ch = 0; ch < outChanNum; ch++) { // first zero them because an exception might be thrown imTempFile[ch] = null; imFloatF[ch] = null; } for (ch = 0; ch < outChanNum; ch++) { imTempFile[ch] = IOUtil.createTempFile(); imFloatF[ch] = new FloatFile(imTempFile[ch], GenericFile.MODE_OUTPUT); } } progLen += outLength; } else { gain = (float) (Param.transform(pr.para[PR_GAIN], Param.ABS_AMP, ampRef, null)).value; wetGain *= gain; dryGain *= gain; } // .... check running .... if (!threadRunning) break topLevel; // ----==================== the real stuff ====================---- framesRead = 0; framesWritten = 0; while (threadRunning && (framesWritten < outLength)) { // ---- choose chunk len ---- len = Math.min(8192, outLength - framesWritten); if (pre > 0) { len = Math.min(len, pre); } else if (inLength > 0) { len = Math.min(len, inLength); } else { len = Math.min(len, post); } // ---- read input chunks ---- if (pre > 0) { Util.clear(reInBuf); if (complex) { Util.clear(imInBuf); } pre -= len; } else if (inLength > 0) { if (pr.bool[PR_REVERSE]) { // ---- read reversed ---- reInF.seekFrame(inOff - framesRead - len); reInF.readFrames(reInBuf, 0, len); for (ch = 0; ch < reInStream.channels; ch++) { convBuf1 = reInBuf[ch]; for (i = 0, j = len - 1; i < j; i++, j--) { f1 = convBuf1[j]; convBuf1[j] = convBuf1[i]; convBuf1[i] = f1; } } if (pr.bool[PR_HASIMINPUT]) { imInF.seekFrame(inOff - framesRead - len); imInF.readFrames(imInBuf, 0, len); for (ch = 0; ch < imInStream.channels; ch++) { convBuf1 = imInBuf[ch]; for (i = 0, j = len - 1; i < j; i++, j--) { f1 = convBuf1[j]; convBuf1[j] = convBuf1[i]; convBuf1[i] = f1; } } } else if (complex) { Util.clear(imInBuf); } } else { // ---- read normal ---- reInF.readFrames(reInBuf, 0, len); if (pr.bool[PR_HASIMINPUT]) { imInF.readFrames(imInBuf, 0, len); } else if (complex) { Util.clear(imInBuf); } } inLength -= len; framesRead += len; } else { Util.clear(reInBuf); if (complex) { Util.clear(imInBuf); } post -= len; } progOff += len; // .... progress .... setProgression((float) progOff / (float) progLen); // .... check running .... if (!threadRunning) break topLevel; // ---- save dry signal ---- for (ch = 0; ch < outChanNum; ch++) { convBuf1 = reInBuf[ch]; convBuf2 = reOutBuf[ch]; for (i = 0; i < len; i++) { convBuf2[i] = convBuf1[i] * dryGain; } if (complex) { convBuf1 = imInBuf[ch]; convBuf2 = imOutBuf[ch]; for (i = 0; i < len; i++) { convBuf2[i] = convBuf1[i] * dryGain; } } } // ---- rectify + apply input gain ---- for (ch = 0; ch < reInStream.channels; ch++) { convBuf1 = reInBuf[ch]; convBuf2 = imInBuf[ch]; // ---- rectify ---- if (pr.bool[PR_RECTIFY]) { if (complex) { if (polarIn) { for (i = 0; i < len; i++) { convBuf2[i] = 0.0f; } } else { for (i = 0; i < len; i++) { d1 = convBuf1[i]; d2 = convBuf2[i]; convBuf1[i] = (float) Math.sqrt(d1 * d1 + d2 * d2); convBuf2[i] = 0.0f; } } } else { for (i = 0; i < len; i++) { convBuf1[i] = Math.abs(convBuf1[i]); } } } // ---- apply input gain ---- Util.mult(convBuf1, 0, len, inGain); if (complex & !polarIn) { Util.mult(convBuf2, 0, len, inGain); } } // ---- heart of the dragon ---- for (ch = 0; ch < outChanNum; ch++) { convBuf1 = reInBuf[ch]; convBuf2 = imInBuf[ch]; switch (pr.intg[PR_OPERATOR]) { case OP_NONE: // ================ None ================ for (i = 0; i < len; i++) { reOutBuf[ch][i] += wetGain * convBuf1[i]; } if (complex) { for (i = 0; i < len; i++) { imOutBuf[ch][i] += wetGain * convBuf2[i]; } } break; case OP_SIN: // ================ Cosinus ================ if (complex) { for (i = 0; i < len; i++) { reOutBuf[ch][i] += wetGain * (float) Math.sin(convBuf1[i] * Math.PI); imOutBuf[ch][i] += wetGain * (float) Math.sin(convBuf2[i] * Math.PI); } } else { for (i = 0; i < len; i++) { reOutBuf[ch][i] += wetGain * (float) Math.sin(convBuf1[i] * Math.PI); } } break; case OP_SQR: // ================ Square ================ if (complex) { for (i = 0; i < len; i++) { reOutBuf[ch][i] += wetGain * (convBuf1[i] * convBuf1[i] - convBuf2[i] * convBuf2[i]); imOutBuf[ch][i] -= wetGain * (convBuf1[i] * convBuf2[i] * 2); } } else { for (i = 0; i < len; i++) { reOutBuf[ch][i] += wetGain * (convBuf1[i] * convBuf1[i]); } } break; case OP_SQRT: // ================ Square root ================ if (complex) { d3 = phi[ch]; k = wrap[ch]; d4 = k * Constants.PI2; for (i = 0; i < len; i++) { d1 = wetGain * Math.pow(convBuf1[i] * convBuf1[i] + convBuf2[i] * convBuf2[i], 0.25); d2 = Math.atan2(convBuf2[i], convBuf1[i]); if (d2 - d3 > Math.PI) { k--; d4 = k * Constants.PI2; } else if (d3 - d2 > Math.PI) { k++; d4 = k * Constants.PI2; } d2 += d4; d3 = d2; d2 /= 2; reOutBuf[ch][i] += (float) (d1 * Math.cos(d2)); imOutBuf[ch][i] += (float) (d1 * Math.sin(d2)); } phi[ch] = d3; wrap[ch] = k; } else { for (i = 0; i < len; i++) { f1 = convBuf1[i]; if (f1 > 0) { reOutBuf[ch][i] += wetGain * (float) Math.sqrt(f1); } // else undefiniert } } break; case OP_RECT2POLARW: // ================ Rect->Polar (wrapped) ================ for (i = 0; i < len; i++) { d1 = wetGain * Math.sqrt(convBuf1[i] * convBuf1[i] + convBuf2[i] * convBuf2[i]); d2 = Math.atan2(convBuf2[i], convBuf1[i]); reOutBuf[ch][i] += (float) d1; imOutBuf[ch][i] += (float) d2; } break; case OP_RECT2POLAR: // ================ Rect->Polar ================ d3 = phi[ch]; k = wrap[ch]; d4 = k * Constants.PI2; for (i = 0; i < len; i++) { d1 = wetGain * Math.sqrt(convBuf1[i] * convBuf1[i] + convBuf2[i] * convBuf2[i]); d2 = Math.atan2(convBuf2[i], convBuf1[i]); if (d2 - d3 > Math.PI) { k--; d4 = k * Constants.PI2; } else if (d3 - d2 > Math.PI) { k++; d4 = k * Constants.PI2; } d2 += d4; reOutBuf[ch][i] += (float) d1; imOutBuf[ch][i] += (float) d2; d3 = d2; } phi[ch] = d3; wrap[ch] = k; break; case OP_POLAR2RECT: // ================ Polar->Rect ================ for (i = 0; i < len; i++) { f1 = wetGain * convBuf1[i]; reOutBuf[ch][i] += f1 * (float) Math.cos(convBuf2[i]); imOutBuf[ch][i] += f1 * (float) Math.sin(convBuf2[i]); } break; case OP_LOG: // ================ Log ================ if (complex) { d3 = phi[ch]; k = wrap[ch]; d4 = k * Constants.PI2; d5 = carry[ch]; for (i = 0; i < len; i++) { d1 = Math.sqrt(convBuf1[i] * convBuf1[i] + convBuf2[i] * convBuf2[i]); d2 = Math.atan2(convBuf2[i], convBuf1[i]); if (d2 - d3 > Math.PI) { k--; d4 = k * Constants.PI2; } else if (d3 - d2 > Math.PI) { k++; d4 = k * Constants.PI2; } if (d1 > 0.0) { d5 = Math.log(d1); } d2 += d4; reOutBuf[ch][i] += (float) d5; imOutBuf[ch][i] += (float) d2; d3 = d2; } phi[ch] = d3; wrap[ch] = k; carry[ch] = d5; } else { for (i = 0; i < len; i++) { f1 = convBuf1[i]; if (f1 > 0) { reOutBuf[ch][i] += wetGain * (float) Math.log(f1); } // else undefiniert } } break; case OP_EXP: // ================ Exp ================ if (complex) { for (i = 0; i < len; i++) { d1 = wetGain * Math.exp(convBuf1[i]); reOutBuf[ch][i] += (float) (d1 * Math.cos(convBuf2[i])); imOutBuf[ch][i] += (float) (d1 * Math.sin(convBuf2[i])); } } else { for (i = 0; i < len; i++) { reOutBuf[ch][i] += wetGain * (float) Math.exp(convBuf1[i]); } } break; case OP_NOT: // ================ NOT ================ for (i = 0; i < len; i++) { lo = ~((long) (convBuf1[i] * 2147483647.0)); reOutBuf[ch][i] += wetGain * (float) ((lo & 0xFFFFFFFFL) / 2147483647.0); } if (complex) { for (i = 0; i < len; i++) { lo = ~((long) (convBuf2[i] * 2147483647.0)); imOutBuf[ch][i] += wetGain * (float) ((lo & 0xFFFFFFFFL) / 2147483647.0); } } break; } } // for outChan progOff += len; // .... progress .... setProgression((float) progOff / (float) progLen); // .... check running .... if (!threadRunning) break topLevel; // ---- write output chunk ---- if (reFloatF != null) { for (ch = 0; ch < outChanNum; ch++) { reFloatF[ch].writeFloats(reOutBuf[ch], 0, len); if (pr.bool[PR_HASIMOUTPUT]) { imFloatF[ch].writeFloats(imOutBuf[ch], 0, len); } } } else { reOutF.writeFrames(reOutBuf, 0, len); if (pr.bool[PR_HASIMOUTPUT]) { imOutF.writeFrames(imOutBuf, 0, len); } } // check max amp for (ch = 0; ch < outChanNum; ch++) { convBuf1 = reOutBuf[ch]; for (i = 0; i < len; i++) { f1 = Math.abs(convBuf1[i]); if (f1 > maxAmp) { maxAmp = f1; } } if (pr.bool[PR_HASIMOUTPUT]) { convBuf1 = imOutBuf[ch]; for (i = 0; i < len; i++) { f1 = Math.abs(convBuf1[i]); if (f1 > maxAmp) { maxAmp = f1; } } } } progOff += len; framesWritten += len; // .... progress .... setProgression((float) progOff / (float) progLen); } // while not framesWritten // ----==================== normalize output ====================---- if (pr.intg[PR_GAINTYPE] == GAIN_UNITY) { peakGain = new Param(maxAmp, Param.ABS_AMP); gain = (float) (Param.transform( pr.para[PR_GAIN], Param.ABS_AMP, new Param(1.0 / peakGain.value, peakGain.unit), null)) .value; f1 = pr.bool[PR_HASIMOUTPUT] ? ((1.0f + getProgression()) / 2) : 1.0f; normalizeAudioFile(reFloatF, reOutF, reOutBuf, gain, f1); if (pr.bool[PR_HASIMOUTPUT]) { normalizeAudioFile(imFloatF, imOutF, imOutBuf, gain, 1.0f); } maxAmp *= gain; for (ch = 0; ch < outChanNum; ch++) { reFloatF[ch].cleanUp(); reFloatF[ch] = null; reTempFile[ch].delete(); reTempFile[ch] = null; if (pr.bool[PR_HASIMOUTPUT]) { imFloatF[ch].cleanUp(); imFloatF[ch] = null; imTempFile[ch].delete(); imTempFile[ch] = null; } } } // .... check running .... if (!threadRunning) break topLevel; // ---- Finish ---- reOutF.close(); reOutF = null; reOutStream = null; if (imOutF != null) { imOutF.close(); imOutF = null; imOutStream = null; } reInF.close(); reInF = null; reInStream = null; if (pr.bool[PR_HASIMINPUT]) { imInF.close(); imInF = null; imInStream = null; } reOutBuf = null; imOutBuf = null; reInBuf = null; imInBuf = null; // inform about clipping/ low level handleClipping(maxAmp); } catch (IOException e1) { setError(e1); } catch (OutOfMemoryError e2) { reOutBuf = null; imOutBuf = null; reInBuf = null; imInBuf = null; convBuf1 = null; convBuf2 = null; System.gc(); setError(new Exception(ERR_MEMORY)); } // ---- cleanup (topLevel) ---- convBuf1 = null; convBuf2 = null; if (reInF != null) { reInF.cleanUp(); reInF = null; } if (imInF != null) { imInF.cleanUp(); imInF = null; } if (reOutF != null) { reOutF.cleanUp(); reOutF = null; } if (imOutF != null) { imOutF.cleanUp(); imOutF = null; } if (reFloatF != null) { for (ch = 0; ch < reFloatF.length; ch++) { if (reFloatF[ch] != null) { reFloatF[ch].cleanUp(); reFloatF[ch] = null; } if (reTempFile[ch] != null) { reTempFile[ch].delete(); reTempFile[ch] = null; } } } if (imFloatF != null) { for (ch = 0; ch < imFloatF.length; ch++) { if (imFloatF[ch] != null) { imFloatF[ch].cleanUp(); imFloatF[ch] = null; } if (imTempFile[ch] != null) { imTempFile[ch].delete(); imTempFile[ch] = null; } } } } // process()
protected void compute() { n = (int) ni[0].parseInput(); t0 = ni[1].parseInput(); deltat = ni[2].parseInput(); x1 = ni[3].parseInput(); x2 = ni[4].parseInput(); sigma = ni[5].parseInput(); // generate data points t = new DatanVector(n); y = new DatanVector(n); dy = new DatanVector(n); rand = DatanRandom.standardNormal(n); for (int i = 0; i < n; i++) { t.setElement(i, t0 + (double) i * deltat); y.setElement(i, x1 * Math.pow(t.getElement(i), x2) + sigma * rand[i]); dy.setElement(i, sigma); } // find 1st approximation of unknowns by method of log-log plot tlog = new double[n]; ylog = new double[n]; dellog = new double[n]; int npos = 0; for (int i = 0; i < n; i++) { if (t.getElement(i) > 0. && y.getElement(i) > 0.) { tlog[npos] = Math.log(t.getElement(i)); ylog[npos] = Math.log(y.getElement(i)); dellog[npos] = 1.; npos++; } } DatanVector vtlog = new DatanVector(npos); DatanVector vylog = new DatanVector(npos); DatanVector vdellog = new DatanVector(npos); for (int j = 0; j < npos; j++) { vtlog.setElement(j, tlog[j]); vylog.setElement(j, ylog[j]); vdellog.setElement(j, dellog[j]); } LsqPol lp = new LsqPol(vtlog, vylog, vdellog, 2); x = lp.getResult(); x.setElement(0, Math.exp(x.getElement(0))); df.writeLine(" x = " + x.toString()); // perform fit int[] list = {1, 1}; powerlaw = new Powerlaw(); LsqNon ln = new LsqNon(t, y, dy, x, list, powerlaw); x = ln.getResult(); x1 = x.getElement(0); x2 = x.getElement(1); cov = ln.getCovarianceMatrix(); delx1 = Math.sqrt(cov.getElement(0, 0)); delx2 = Math.sqrt(cov.getElement(1, 1)); rho = cov.getElement(1, 0) / (delx1 * delx2); m = ln.getChiSquare(); p = 1. - StatFunct.cumulativeChiSquared(m, n - 1); // curve of fitted exponential xpl = new double[1001]; ypl = new double[1001]; dpl = (double) (n - 1) * deltat / 1000.; for (int i = 0; i < 1001; i++) { xpl[i] = t0 + (double) i * dpl; ypl[i] = x1 * Math.pow(xpl[i], x2); } // prepare data points for plotting datx = new double[n]; daty = new double[n]; datsx = new double[n]; datsy = new double[n]; datrho = new double[n]; for (int i = 0; i < n; i++) { datx[i] = t.getElement(i); daty[i] = y.getElement(i); datsx[i] = 0.; datsy[i] = dy.getElement(i); datrho[i] = 0.; } // display data and fitted curve caption = "x_1#=" + String.format(Locale.US, "%5.2f", x1) + ", x_2#=" + String.format(Locale.US, "%5.2f", x2) + ", &D@x_1#=" + String.format(Locale.US, "%5.2f", delx1) + ", &D@x_2#=" + String.format(Locale.US, "%5.2f", delx2) + ", &r@=" + String.format(Locale.US, "%5.2f", rho) + ", M=" + String.format(Locale.US, "%5.2f", m) + ", P=" + String.format(Locale.US, "%6.4f", p); new GraphicsWithDataPointsAndPolyline( getClass().getName(), "", xpl, ypl, 1, .3, datx, daty, datsx, datsy, datrho, "t", "y", caption); }
public double evaluate(double x) { return Math.log(x * x + 1) - Math.exp(0.4 * x) * Math.cos(Math.PI * x); }
// handy static methods public static double log10(double val) { return Math.log(val) * LOG10SCALE; }
/** * Includes a static function for selecting and labeling graph axis tic labels. given a numeric * range and a maximum number of tics, this class can produce a list of labels with the nicest round * numbers not exceeding a given maximum number of labels. the label generation code was extracted * from the public domain <a href="http://ptolemy.eecs.berkeley.edu/">Ptolomy project</a> at UC * Berkeley, taken from ptolemy/plot/PlotBox.java. * * <p>We added another static method to compute and draw an axis into a given AWT Graphics object. i * extracted the code for producing linear labels and threw out the vast majority of code that * attempted to produce log scale labels since that code was very broken. it was noted int the * Ptolomy code that the log label generation was itself based on a file named xgraph.c by David * Harrisonmy, and the comments say that the original code breaks down in certain cases. my drawAxis * method can still draw nicely labeling log scale axes because i simply use the linear scale label * generation code from Ptolomy and plot the tics in their proper locations on a log scale. the * resulting code produced exactly the same results as the Ptolemy code for log scales in those * ranges where the Ptolemy code did work, so this design is much better in all cases and uses only * a fraction of the original complexity. still, it can probably be further improved though the * exact problem is not well defined. * * @author M.Green and S.Chekanov */ public class Axis { private static final boolean DEBUG = false; public static final int X_AXIS = 0, Y_AXIS = 1; // For use in calculating log base 10. A log times this is a log base 10. private static final double LOG10SCALE = 1 / Math.log(10); // handy static methods public static double log10(double val) { return Math.log(val) * LOG10SCALE; } public static double exp10(double val) { return Math.exp(val / LOG10SCALE); } public static float flog10(double val) { return (float) log10(val); } public static float fexp10(double val) { return (float) exp10(val); } /** * Calculation of the separation length between tics. Some smart rounding algorithms are needed to * get the scaling properly in case of data going to 10.3 or so... Useful stuff stolen from the * Gnuplot sources, thank you guys!! */ public static double calculateTicSep(double min, double max, int maxNumberOfTicks) { double xnorm, tic, posns; double lrange = log10(Math.abs(min - max)); double fl = Math.floor(lrange); xnorm = Math.pow(10.0, lrange - fl); posns = maxNumberOfTicks / xnorm; if (posns > 40) tic = 0.05; // eg 0, .05, .10, ... else if (posns > 20) tic = 0.1; // eg 0, .1, .2, ... else if (posns > 10) tic = 0.2; // eg 0,0.2,0.4,... else if (posns > 4) tic = 0.5; // 0,0.5,1, else if (posns > 1) tic = 1; // 0,1,2,.... else if (posns > 0.5) tic = 2; // 0, 2, 4, 6 else if (posns > 0.2) tic = 10; // 0, 10, 100, 6 else tic = Math.ceil(xnorm); tic *= Math.pow(10.0, fl); return tic; } /** Precompute number of ticks */ public static int calculateTicNumber( double ticMinVal, double ticMaxVal, double xStep, boolean isLog) { int n = 0; // System.out.println("\n-- calculateTicNumber="); // System.out.println("Min="+Double.toString(ticMinVal)); // System.out.println("Max="+Double.toString(ticMaxVal)); // System.out.println("Max="+Double.toString(xStep)); if (isLog == false) { double xStart = xStep * Math.ceil(ticMinVal / xStep); for (double xpos = xStart; xpos <= ticMaxVal; xpos += xStep) n++; } else { int t1 = 0; int t2 = 0; if (ticMinVal > 0) t1 = (int) Math.floor(log10(ticMinVal) - 0.5); if (ticMinVal < 0) t1 = -1 * (int) Math.floor(log10(-1 * ticMinVal) - 0.5); if (ticMaxVal > 0) t2 = (int) Math.floor(log10(ticMaxVal) + 1.0); if (ticMaxVal < 0) t2 = -1 * (int) Math.floor(log10(-1 * ticMaxVal) + 1.0); for (int i = t1; i < t2 + 1; i++) n++; } // System.out.println("Nr of ticks="+Integer.toString(n)); return n; } /** * this is the central method of this class. takes axis range parameters and produces a list of * string representations of nicely rounded numbers within the given range. these strings are * intended for use as axis tic labels. note: to find out where to plot each tic label simply use * <br> * <code>float ticval = Float.parseFloat(ticstring);</code> * * @param ticMinVal no tics will be created for less than this value. * @param ticMaxVal no tics will be created for greater than this value. * @param maxTics returned vector will contain no more labels than this number. * @param isLog set to true in case of log10 numbers * @return a Vector containing formatted label strings which should also be parsable into floating * point numbers (in order to plot them). */ public static Vector<String> computeTicks( double ticMinVal, double ticMaxVal, int maxTicks, boolean isLog) { // double xStep = roundUp((ticMaxVal-ticMinVal)/maxTicks); double xStep = calculateTicSep(ticMinVal, ticMaxVal, maxTicks); int numfracdigits = numFracDigits(xStep); // Compute x starting point so it is a multiple of xStep. double xStart = xStep * Math.ceil(ticMinVal / xStep); Vector xgrid = null; Vector<String> labels = new Vector<String>(); // Label the axis. The labels are quantized so that // they don't have excess resolution. if (!isLog) { for (double xpos = xStart; xpos <= ticMaxVal; xpos += xStep) { String snum = formatNum(xpos, numfracdigits); labels.addElement(snum); } // log scale: special case } else { int t1 = 0; int t2 = 0; if (ticMinVal > 0) t1 = (int) Math.floor(log10(ticMinVal) - 0.5); if (ticMinVal < 0) t1 = -1 * (int) Math.floor(log10(-1 * ticMinVal) - 0.5); if (ticMaxVal > 0) t2 = (int) Math.floor(log10(ticMaxVal) + 1.0); if (ticMaxVal < 0) t2 = -1 * (int) Math.floor(log10(-1 * ticMaxVal) + 1.0); // System.out.println("min = " + xmin + ", max = " + xmax); for (int i = t1; i < t2 + 1; i++) { double pp = Math.pow(10.0, i); // System.out.println(pp); labels.addElement(Double.toString(pp)); } } return labels; } /** * high-level method for drawing a chart axis line plus labeled tic marks. introduces a dependancy * on AWT because it takes a Graphics parameter. perhaps this method belongs in some higher-level * class but i added it here since it's highly related with the tic lable generation code. * * @author Melinda Green * @param axis is one of Axis.X_AXIS or Axis.Y_AXIS. * @param maxTics is the maximum number of labeled tics to draw. note: the actual number drawn may * be less. * @param lowVal is the smallest value tic mark that may be drawn. note: the lowest valued tic * label may be greater than this limit. * @param highVal is the largest value tic mark that may be drawn. note: the highest valued tic * label may be less than this limit. * @param screenStart is the coordinate in the low valued direction. * @param screenEnd is the coordinate in the high valued direction. * @param offset is the coordinate in the direction perpendicular to the specified direction. * @param logScale is true if a log scale axis is to be drawn, false for a linear scale. * @param screenHeight is needed to flip Y coordinates. * @param g is the AWT Graphics object to draw into. note: all drawing will be done in the current * color of the given Graphics object. */ public static void drawAxis( int axis, int maxTics, int ticLength, float lowVal, float highVal, int screenStart, int screenEnd, int screenOffset, boolean logScale, int screenHeight, Graphics g) { if (logScale && (lowVal == 0 || highVal == 0)) throw new IllegalArgumentException("Axis.drawAxis: zero range value not allowed in log axes"); if (axis == X_AXIS) // horizontal baseline g.drawLine(screenStart, screenHeight - screenOffset, screenEnd, screenHeight - screenOffset); else // vertical baseline g.drawLine(screenOffset, screenStart, screenOffset, screenEnd); Vector tics = Axis.computeTicks(lowVal, highVal, maxTics, logScale); // nice // round // numbers // for // tic // labels int last_label_end = axis == X_AXIS ? -88888 : 88888; String dbgstr = "tics: "; for (Enumeration e = tics.elements(); e.hasMoreElements(); ) { String ticstr = (String) e.nextElement(); if (DEBUG) dbgstr += ticstr + ", "; float ticval = Float.parseFloat(ticstr); int tic_coord = screenStart; Dimension str_size = stringSize(ticstr, g); tic_coord += plotValue(ticval, lowVal, highVal, screenStart, screenEnd, logScale, screenHeight); if (axis == X_AXIS) { // horizontal axis == vertical tics g.drawLine( tic_coord, screenHeight - screenOffset, tic_coord, screenHeight - screenOffset + ticLength); if (tic_coord - str_size.width / 2 > last_label_end) { g.drawString( ticstr, tic_coord - str_size.width / 2, screenHeight - screenOffset + str_size.height + 5); last_label_end = tic_coord + str_size.width / 2 + str_size.height / 2; } } else { // vertical axis == horizontal tics tic_coord = screenHeight - tic_coord; // flips Y coordinates g.drawLine(screenOffset - ticLength, tic_coord, screenOffset, tic_coord); if (tic_coord - str_size.height / 3 < last_label_end) { g.drawString( ticstr, screenOffset - ticLength - str_size.width - 5, tic_coord + str_size.height / 3); last_label_end = tic_coord - str_size.height; } } } if (DEBUG) System.out.println(dbgstr); } // end drawAxis /** * lower level method to determine a screen location where a given value should be plotted given * range, type, and screen information. the "val" parameter is the data value to be plotted * * @author Melinda Green * @param val is a data value to be plotted. * @return pixel offset (row or column) to draw a screen representation of the given data value. * i.e. <i>where</i> along an axis in screen coordinates the caller should draw a * representation of the given value. * @see drawAxis(int,int,int,float,float,int,int,int,boolean,int,Graphics) */ public static int plotValue( float val, float lowVal, float highVal, int screenStart, int screenEnd, boolean logScale, int screenHeight) { if (logScale && (lowVal == 0 || highVal == 0 || val == 0)) throw new IllegalArgumentException("Axis.drawAxis: zero range value not allowed in log axes"); int screen_range = screenEnd - screenStart; // in pixels if (logScale) { float log_low = flog10(lowVal), log_high = flog10(highVal), log_val = flog10(val); float log_range = log_high - log_low; float pixels_per_log_unit = screen_range / log_range; return (int) ((log_val - log_low) * pixels_per_log_unit + .5); } else { float value_range = highVal - lowVal; // in data value units float pixels_per_unit = screen_range / value_range; return (int) ((val - lowVal) * pixels_per_unit + .5); } } /* * Given a number, round up to the nearest power of ten times 1, 2, or 5. * * Note: The argument must be strictly positive. */ private static double roundUp(double val) { int exponent = (int) Math.floor(log10(val)); val *= Math.pow(10, -exponent); if (val > 5.0) val = 10.0; else if (val > 2.0) val = 5.0; else if (val > 1.0) val = 2.0; val *= Math.pow(10, exponent); return val; } /* * Return the number of fractional digits required to display the given * number. No number larger than 15 is returned (if more than 15 digits are * required, 15 is returned). */ private static int numFracDigits(double num) { int numdigits = 0; while (numdigits <= 15 && num != Math.floor(num)) { num *= 10.0; numdigits += 1; } return numdigits; } // Number format cache used by formatNum. // Note: i'd have put the body of the formatNum method below into // a synchronized block for complete thread safety but that causes // an abscure null pointer exception in the awt event thread. // go figure. private static NumberFormat numberFormat = null; /* * Return a string for displaying the specified number using the specified * number of digits after the decimal point. NOTE: java.text.NumberFormat is * only present in JDK1.1 We use this method as a wrapper so that we can * cache information. */ private static String formatNum(double num, int numfracdigits) { if (numberFormat == null) { // Cache the number format so that we don't have to get // info about local language etc. from the OS each time. // numberFormat = NumberFormat.getInstance(); numberFormat = NumberFormat.getInstance(Locale.ENGLISH); // force to not include commas because we want the strings // to be parsable back into numeric values. - DRG numberFormat.setGroupingUsed(false); } numberFormat.setMinimumFractionDigits(numfracdigits); numberFormat.setMaximumFractionDigits(numfracdigits); return numberFormat.format(num); } /** * handy little utility for determining the length in pixels the given string will use if drawn * into the given Graphics object. Note: perhaps belongs in some utility package. */ public static Dimension stringSize(String str, Graphics g) { if (g instanceof Graphics2D) { java.awt.geom.Rectangle2D bounds = g.getFont().getStringBounds(str, ((Graphics2D) g).getFontRenderContext()); return new Dimension((int) (bounds.getWidth() + .5), (int) (bounds.getHeight() + .5)); } else return new Dimension(g.getFontMetrics().stringWidth(str), g.getFontMetrics().getHeight()); } // // TEST CODE FROM HERE DOWN // private static class TestPanel extends JPanel { private float curLowVal, curHighVal; private boolean logScale; public TestPanel(float initialLow, float initialHigh) { curLowVal = initialLow; curHighVal = initialHigh; } public void setLogScale(boolean logScale) { this.logScale = logScale; repaint(); } public void setLow(float val) { curLowVal = val; repaint(); } public void setHigh(float val) { curHighVal = val; repaint(); } public void paint(Graphics g) { super.paint(g); drawAxis( Axis.X_AXIS, 10, 5, curLowVal, curHighVal, 50, getWidth() - 50, 50, logScale, getHeight(), g); drawAxis( Axis.Y_AXIS, 10, 5, curLowVal, curHighVal, 50, getHeight() - 50, 50, logScale, getHeight(), g); g.drawString("Current Slider Range: " + curLowVal + " --> " + curHighVal, 10, 20); } } private static void addField( Container into, Component c, GridBagConstraints gbc, int x, int y, int w, int h, int wx, int wy) { gbc.gridx = x; gbc.gridy = y; gbc.gridwidth = w; gbc.gridheight = h; gbc.weightx = wx; gbc.weighty = wy; into.add(c, gbc); } /** simple example program for Axis class. */ public static void main(String args[]) { /* * final float INITIAL_MIN_LOW=1, INITIAL_MAX_HIGH=1000; final TestPanel * axis = new TestPanel(INITIAL_MIN_LOW, INITIAL_MAX_HIGH); final JFrame * frame = new JFrame("Axis Test"); JPanel mainpanel = new JPanel(new * BorderLayout()); mainpanel.add("Center", axis); JPanel controls = new * JPanel(); final JCheckBox logScale = new JCheckBox("Log"); * logScale.addActionListener(new ActionListener() { public void * actionPerformed(ActionEvent ae) { * axis.setLogScale(logScale.isSelected()); } }); * logScale.setSelected(true); axis.setLogScale(true); * * final JTextField minlow = new JTextField(""+INITIAL_MIN_LOW, 6); * final FloatSlider lowSlider = new FloatSlider(JSlider.HORIZONTAL, * INITIAL_MIN_LOW, 100, 1, 1000, 2000, false); final FloatSlider * highSlider = new FloatSlider(JSlider.HORIZONTAL, INITIAL_MAX_HIGH, * 100, 1, 1000, 2000, false); final JTextField maxhigh = new * JTextField(""+INITIAL_MAX_HIGH, 6); GridBagLayout gridbag = new * GridBagLayout(); controls.setLayout(gridbag); GridBagConstraints con * = new GridBagConstraints(); con.fill = GridBagConstraints.BOTH; * con.insets = new Insets(0, 10, 0, 0); addField(controls, logScale, * con, 0, 0, 1, 1, 5, 100); addField(controls, new * JLabel("min low value"), con, 1, 0, 1, 1, 10, 100); * addField(controls, minlow, con, 2, 0, 1, 1, 10, 100); * addField(controls, lowSlider, con, 3, 0, 1, 1, 50, 100); * addField(controls, highSlider, con, 4, 0, 1, 1, 50, 100); * addField(controls, new JLabel("max high value"), con, 5, 0, 1, 1, 10, * 100); addField(controls, maxhigh, con, 6, 0, 1, 1, 10, 100); * mainpanel.add("South", controls); KeyListener limitsWatcher = new * KeyAdapter() { public void keyTyped(KeyEvent ke) { if(ke.getKeyChar() * == KeyEvent.VK_ENTER) { float newminlow = * Float.parseFloat(minlow.getText()); float newmaxhigh = * Float.parseFloat(maxhigh.getText()); lowSlider.setAll(newminlow, * newmaxhigh, lowSlider.getFloatValue()); highSlider.setAll(newminlow, * newmaxhigh, highSlider.getFloatValue()); } } }; * minlow.addKeyListener(limitsWatcher); * maxhigh.addKeyListener(limitsWatcher); AdjustmentListener * slider_watcher = new AdjustmentListener() { public void * adjustmentValueChanged(AdjustmentEvent ae) { if (ae.getSource() == * lowSlider) axis.setLow((float)lowSlider.getFloatValue()); else * axis.setHigh((float)highSlider.getFloatValue()); } }; * lowSlider.addAdjustmentListener(slider_watcher); * highSlider.addAdjustmentListener(slider_watcher); * frame.getContentPane().add(mainpanel); frame.setSize(new * Dimension(1000, 400)); * frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); * frame.setVisible(true); */ } // end main }