2

I'm trying do define an interface in which I want to plot some values received by an external device. These values are received with a frequency that can be set through the interface. Of course the period of the plot should change according to the period defined by the user. So I started to define the followint Chart:

int periodMs = 200;
MilliDTSC dataset = new MilliDTSC(1,100, new MultipleOfMillisecond(periodMs));
dataset.setTimeBase(new MultipleOfMillisecond(periodMs))
dataset.addSeries(zeroSeries()),0,"Zero data") // zeroSeries returs a series with values set to 0
JFreeChart chart = createChart(dataset) // create the chart and set ranges and legends
ChartPanel panel = new ChartPanel(panel);

MilliDTSC is the following class, as suggested here:

public class MilliDTSC extends DynamicTimeSeriesCollection{
  public MilliDTSC(int nSeries, int nMoments, RegularTimePeriod timeSample){
    super(nSeries, nMoments, timeSample);
    if(timeSample instanceof Millisecond)
      this.pointsInTime = new Millisecond[nMoments]
    else if (timeSample instanceof MultipleOfMillisecond)
      this.pointsInTime = new MultipleOfMillisecond[nMoments]
  }
}

MultipleOfMillisecond is the following class:

public class MultipleOfMilliseconds extends Millisecond{
  MulitpleOfMilliseconds(int periodMs){
    this.periodMs = periodMs
  }

  public RegularTimePeriod previous(){
    RegularTimePeriod result = null;
    if(getMillisecond() - periodMs >= FIRST_MILLISECOND_IN_SECOND)
      result = new Millisecond((int)getMillisecond - periodMs, getSecond());
    else{
      Second previous = (Second)getSecond().previous();
      if(previous!=null)
        result = new Millisecond((int)(getMillisecond() - periodMS + LAST_MILLISECOND_IN_SECOND + 1), previous);
    }
    return result;
  }
  // similar for next()
}

I add sample to the series in the following way:

dataset.advanceTime();
dataset.appendData(newData);

What I expected is that once I fixed the period to 200 ms the chart reports on the X label more or less 5 time values:

00:00:00.000 00:00:05.000 00:00:10.000 00:00:15.000 00:00:20.000

And I expected 25 samples in each "space".

What happen instead is that I have 25 samples for each "space" but the chart reports the following values on the X label:

00:00:00.000 00:00:00.025 00:00:00.050 00:00:00.075 00:00:00.100

It seems that the period is 1ms but I'm adding samples very 200 ms.

How can I solve the problem? If I was not clear pleas tell me. Thanks!!

Community
  • 1
  • 1
Maverik
  • 2,358
  • 6
  • 34
  • 44

3 Answers3

4

I think because you have this:

public class MultipleOfMilliseconds extends Millisecond
//                                          ^^^^^^^^^^^

this is true:

if(timeSample instanceof Millisecond)

If you change the ordering of the tests you might have better luck:

if(timeSample instanceof MultipleOfMillisecond)
  this.pointsInTime = new MultipleOfMillisecond[nMoments];
else if (timeSample instanceof Millisecond)
  this.pointsInTime = new Millisecond[nMoments];
clstrfsck
  • 14,715
  • 4
  • 44
  • 59
  • You are right, it is an error. Anyway it doesn't work. It raise an exception – Maverik Jul 28 '11 at 11:28
  • I fixed the excpetion. It was in the next and previuos methods which return millisecond instead of MultimpleOfMillisecond. Anyway it doesn't work. – Maverik Jul 28 '11 at 11:45
  • Yes I can, Is better if I update the question or somethingelse? I think I found a good solution – Maverik Jul 28 '11 at 12:32
  • I think updating the question, but if you have resolved the problem maybe you could post it as a solution and possibly accept also. – clstrfsck Jul 28 '11 at 12:37
  • Yeah, I have to wait for posting my awn answer because I don't have enough reputation. – Maverik Jul 28 '11 at 12:56
  • @Maverik Im collecting data each 250 microseconds, i need to limit the visible points in screen for performance purposes like 1000 points and adjust the space between them according to the zoom. So if the time range is 10 sec, show 1000 points at 10ms, if range is 1 sec show 1000 points at 1ms, range 250 ms show 1000 points at 250 microseconds. I was thinking in creating multiple dataseries and switching between them, do you have a better idea? Using DynamicSeries? – justcode May 02 '18 at 18:12
2

This is the solution I implemented. I reported only the methods that I changed. It was a stupid error :D

public MilliDTSC(int nSeries, int nMoments, RegularTimePeriod timeSample) {
  super(nSeries, nMoments, timeSample);
  if(timeSample instanceof MultipleOfMillisecond){
    this.pointsInTime = new MultipleOfMillisecond[nMoments];
  }else if (timeSample instanceof Millisecond) {
    this.pointsInTime = new Millisecond[nMoments];
  } 
}

public class MultipleOfMillisecond extends Millisecond {

  private static final long serialVersionUID = 1L;
  private int periodMs = 100;

  public MultipleOfMillisecond(int periodMs){
    super();
    this.periodMs = periodMs;
  }

  public MultipleOfMillisecond(int periodMs, int millisecond, Second second){
    super(millisecond, second);
    this.periodMs = periodMs;
  }

  @Override
  public RegularTimePeriod next() {
    
    RegularTimePeriod result = null;
    if(getMillisecond() + periodMs <= LAST_MILLISECOND_IN_SECOND){
        result = new MultipleOfMillisecond( periodMs, (int)(getMillisecond() + periodMs), getSecond());
    }else{
        Second next = (Second)getSecond().next();
        if(next != null){
            result = new MultipleOfMillisecond(periodMs, (int)(getMillisecond() + periodMs - LAST_MILLISECOND_IN_SECOND - 1), next);
        }
    }
    return result;
    
  }

  @Override
  public RegularTimePeriod previous() {
    
    RegularTimePeriod result = null;
    if(getMillisecond() - periodMs >= FIRST_MILLISECOND_IN_SECOND){
        result = new MultipleOfMillisecond(periodMs, (int)getMillisecond() - periodMs, getSecond());
    }else{
        Second previous = (Second)getSecond().previous();
        if(previous != null){
            result = new MultipleOfMillisecond(periodMs, (int)(getMillisecond() - periodMs + LAST_MILLISECOND_IN_SECOND + 1), previous);
        }
    }
    return result;
    
  } 
}

Now I have 10 samples in 5 seconds, i set the period to 500 ms

Now I have 10 samples in 5 seconds, i set the period to 500 ms

Community
  • 1
  • 1
Maverik
  • 2,358
  • 6
  • 34
  • 44
  • +1 Now I see what you meant. This looks more flexible than creating an individual `HemiSecond` class. You may also need to implement `Comparable`. – trashgod Jul 28 '11 at 20:08
  • Maybe yes. I though that the comparable methods implemented in Milliseconds were good also for my class. – Maverik Jul 28 '11 at 21:04
  • Thanks for posting your solution, BTW. I would suggest accepting @msandiford's insightful answer, as you get two points for accepting an answer other than your own. See the [faq] for details. – trashgod Jul 29 '11 at 10:58
1

Instead, use the original MilliDTSC & Millisecond, and invoke advanceTime() and append the old data as required before appending the new data. Using 200 ms as an example, do something like this:

float[] newData = new float[1];
float[] oldData = new float[1];

@Override
public void actionPerformed(ActionEvent e) {
    newData[0] = randomValue();
    oldData[0] = newData[0];
    for (int i = 0; i < 200; i++) {
        dataset.advanceTime();
        dataset.appendData(oldData);
    }
    dataset.appendData(newData);
}

Note that there are now 5 samples/second, spaced 200 ms apart.

enter image description here

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I'm sorry. It's not working for me. I have a method `update(float value)`that I call each time I receive a new data, so each time every 200 ms. If I put in the update method the code you wrote in the actionPerformed method, my chart reports a single line. – Maverik Jul 28 '11 at 11:24
  • Ok, I think you are plotting the same value 200 times and so that your series is much longer than 100 (as I defined in my code). Anyway I don't want to see the step bewtween the values. It is not the real behavior of the system. I want a line with a skew that depends on the difference between the two following values. – Maverik Jul 28 '11 at 11:34
  • Then simply call `advanceTime()` and `omit `appendData(oldData)`. – trashgod Jul 28 '11 at 13:36
  • Thanks but it didn't worked for me. I found a solution by extending the class Milliseconds. I will publish it in three hours. I have not enough reputation so I cannot answer to my question for 8 hours. – Maverik Jul 28 '11 at 14:48