Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Series sets DataSource null #156

Open
brainbytes42 opened this issue Dec 13, 2016 · 1 comment
Open

Series sets DataSource null #156

brainbytes42 opened this issue Dec 13, 2016 · 1 comment
Assignees

Comments

@brainbytes42
Copy link

First of all, thanks for GRAL, nice work.

I'm aiming for an application, where one can click on data-points and where a point gets rendered as part of a graph (which is fairly easy, using a custom GraphLineRenderer). Both usecases need a reverse-link from DataPoint to the data's source and it's respective row.

As long as I use the DataTable as source for the Plot, everything is fine, the row is mapped to the data-source and I can use the row as identifier. (In the demo-code, I used UUID as placeholder for the "real" linking.

But if I flatten the view using DataSeries, the source gets null and the row is an other object.

Maybe I got something wrong, but isn't the concept behind DataSources and Series to preserve the original data's mapping and add another view?

Or is there another BestPractice to link from a particular DataPoint (which provides only row and col apart from it's position or values) to it's original source?

Thanks.

import de.erichseifert.gral.data.DataSeries;
import de.erichseifert.gral.data.DataTable;
import de.erichseifert.gral.data.Row;
import de.erichseifert.gral.plots.XYPlot;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Stream;

public class SourceNullDemo {

  public SourceNullDemo() {

    // dummy-mapping
    final Map<UUID, Row> rowMapping = new HashMap<>();

    // create DataTable
    @SuppressWarnings("unchecked")
    final DataTable data = new DataTable(Double.class, Double.class, Double.class);
    System.out.println("DataTable:" + data + "\n");

    // create random data and store the mapping
    final Random random = new Random();
    Stream.generate(() -> UUID.randomUUID()).limit(3).forEach(uuid -> {
      data.add(random.nextDouble(), random.nextDouble(), random.nextDouble());
      rowMapping.put(uuid, data.getRow(data.getRowCount() - 1));
    });

    // so long, mapping is ok.
    rowMapping.forEach((uuid, row) -> System.out.println(uuid + " -> " + row));

    // create two plots, one for the data and one for a projection using series.
    final Map<String, XYPlot> plots = new LinkedHashMap<>();
    plots.put("new XYPlot(data)", new XYPlot(data));
    plots.put("new XYPlot(new DataSeries(data))", new XYPlot(new DataSeries(data, 0, 1)));

    // query each plot
    plots.forEach((descr, plot) -> {
      System.out.println("\n" + descr + ":");
      plot.getData().forEach(ds -> {
        // datasource is null for series!
        System.out.println(" > DataSource: " + ds);
        for (int i = 0; i < ds.getRowCount(); i++) {
          // row's source is null for series. and different object than for same from data.
          System.out.println(
              "   " + ds.getRow(i) + " @ " + Integer.toHexString(Objects.hash(ds.getRow(i))));
          for (int j = 0; j < ds.getColumnCount(); j++) {
            // projection preserves third column, but sets it null?!
            System.out.println("   = " + ds.get(i, j));
          }
        }
      });
    });
  }

  public static void main(final String[] args) {
    new SourceNullDemo();
  }

}
@seifertm seifertm self-assigned this Dec 13, 2016
@seifertm
Copy link
Collaborator

Thanks for the report!

First of all, your understanding of DataSource and DataSeries is absolutely correct. DataSeries is a projection of the two-dimensional DataSource.

There are two things leading to your problem here:
The DataSeries being null is merely an issue with the implementation of toString() in DataSeries. DataSeries.toString() returns the name of the series which is null by default. Giving the data series a name like new DataSeries("MyProjection", data, 0, 1) should give more reasonable output on the console.

The third row of the second example is null, because the indices i and j of DataSource.get(int col, int row) are interchanged. You are trying to retrieve the value at column index 2 which does not exist in the projected data, so null is returned.

I admit that this behaviour is not optimal and might be misleading. I will leave the issue open so I won't forget creating new issues for that :)

Finally, you mentioned that Row objects are not the same. This is due to the fact that, historically, GRAL stores data in a two-dimensional structure (DataTable). Rows are merely views (i.e. selections) onto a record of the table. Row objects are created as needed when calling getRow while the actual data is always stored in the underlying DataTable. Issue #136 seeks to changes this, but due to my limited time at the moment, I cannot give an estimate on how long it will take. In the meantime, you might consider using the row index as an identifier, if that helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants