# Schöne Heatmap erzeugen



## iltisjan (25. Jul 2018)

Hi,
ich bin neu hier und noch in den Anfängen der Java-Programmierung.
Ich hoffe, ich bin hier im richtigen Unterforum gelandet...
Meine Frage ist, ob es eine Möglichkeit gibt, eine schöne Heatmap aus einem 2-dimensionalen double Array ( double[][] ) zu erzeugen.
In etwa so habe ich es mir vorgestellt (nur halt mit Java statt python):
https://scipython.com/book/chapter-7-matplotlib/examples/a-heatmap-of-boston-temperatures/

Ich habe schon JHeatChart ausprobiert, aber die Heatmap sieht nicht wirklich gut aus und die Auflösung ist auch nicht gerade gut.

Wäre super, wenn jemand eine Lösung für mich hätte, die ich auch verstehe


----------



## mihe7 (25. Jul 2018)

Gibt es eine konkrete Frage dazu, oder willst Du nur, dass jemand für Dich in Google "java heat map" (ohne Anführungszeichen) eintippt und Dir ein paar Links von der ersten Seite postet?


----------



## Xyz1 (25. Jul 2018)

mach ich später mal....


----------



## iltisjan (25. Jul 2018)

Hallo auch.
Danke, dass ich so nett aufgenommen wurde. -.-
Ich bin es ja gewohnt, dass die ersten Antworten meist nicht die Information liefern, die man sich erhofft hat, aber naja. Bedenkt mal eure Verhaltensweise anderen Menschen gegenüber. Würdet ihr auch so reagieren wenn ich direkt vor euch stehen und ganz normal fragen würde? Vermutlich sagt ihr nun: "klar würde ich das". In der Realität sieht es dann aber ganz anders aus. Hoffe ich jedenfalls.
Ich weiß nicht, ob ihr euch erinnert als ihr angefangen habt mit Java zu programmieren, aber da versteht man nicht sofort alles was man so an Code findet. Es geht mir also auch um eine Antwort, die ich verstehe. Wenn mir jetzt einer 200 Zeilen undokumentierten Code als Antwort postet, dann hilft mir das auch nur bedingt.


Zurück zum Thema:
Selbstverständlich habe ich vorher google befragt und wie ich schon erwähnt habe, habe ich auch schon jheatmap getestet, aber für nicht gut empfunden, oder eben ich benutze es nicht richtig. Jedenfalls sieht meine heatmap da nicht gut aus.

Was ich mir als Antwort erhoffe ist eigentlich ob es eine Möglichkeit gibt mit Java eine gut aussehende HeatMap zu erzeugen. Das habe ich aber eigentlich auch in meinem ersten Beitrag schon geschrieben.
Bei google wird eigentlich immer jheatmap von den Leuten erwähnt, aber wie gesagt.. s.o.

Fällt euch eine andere Alternative ein?

Das hier habe ich auch gefunden:
http://www.java2s.com/Code/Java/Swi...ayofdatausingaselectedcolorgradientscheme.htm

Ich weiß jetzt nur nicht genau, wie ich das in mein bestehendes Projekt einbinden kann? Ich würde einfach den kompletten Code in eine neue Klasse übernehmen und dann in meiner bisherigen Klasse ein Objekt der Klasse HeatMap erzeugen (oder nicht?).. und dann?


----------



## httpdigest (25. Jul 2018)

iltisjan hat gesagt.:


> Wäre super, wenn jemand eine Lösung für mich hätte, die ich auch verstehe


Woher sollen Leute denn wissen, was du verstehst?



iltisjan hat gesagt.:


> Es geht mir also auch um eine Antwort, die ich verstehe. Wenn mir jetzt einer 200 Zeilen undokumentierten Code als Antwort postet, dann hilft mir das auch nur bedingt.


Wieviele Zeilen undokumentieren Code kannst du denn verkraften?



iltisjan hat gesagt.:


> Das hier habe ich auch gefunden:
> http://www.java2s.com/Code/Java/Swi...ayofdatausingaselectedcolorgradientscheme.htm
> Ich weiß jetzt nur nicht genau, wie ich das in mein bestehendes Projekt einbinden kann?


Es ist ja als JPanel implementiert, also füge das JPanel einfach als Komponente in irgendein Swing Container hinzu.
Hierfür musst du natürlich erstmal wissen, wie Swing funktioniert.
Google hierzu am besten einmal "Java Swing tutorial" und lies dir die ersten paar Ergebnisse der ersten Seite durch.

Generell ist es bei Fragen wie "_Ich will dies und jenes machen, habe aber keine Ahnung und verstehe auch mögliche Lösungen nicht_" immer schwierig als Antwortgebender, eine für den Fragenden zufriedenstellende Antwort auszuarbeiten.


----------



## mihe7 (25. Jul 2018)

iltisjan hat gesagt.:


> Ich bin es ja gewohnt, dass die ersten Antworten meist nicht die Information liefern, die man sich erhofft hat, aber naja.



Wenn Du das gewohnt bist, könnte es evtl. an Deiner Fragestellung liegen...

Du willst eine Heat Map in Java, die irgendwie so aussieht wie die verlinkte. JHeatMap hast Du ausprobiert, gefällt Dir aber nicht. 

Was soll jetzt irgendjemand aus dieser Info ableiten? Willst Du eine fertige Komponente? Willst Du nur die Grafik selbst oder auch die Beschriftungen dazu? Willst Du eine Komponente selber bauen? Willst Du die HeatMap am Bildschirm anzeigen oder als Grafikdatei ausgeben? Usw. usw. 

Wenn ich Google befrage und dem dritten Link (mbeckler) folge, dann komme ich auf eine Seite, die für mich ziemlich genau danach aussieht, was ich vermute, dass Du haben möchtest - inkl. Beispielcode.



iltisjan hat gesagt.:


> Das hier habe ich auch gefunden:
> http://www.java2s.com/Code/Java/Swi...ayofdatausingaselectedcolorgradientscheme.htm
> 
> Ich weiß jetzt nur nicht genau, wie ich das in mein bestehendes Projekt einbinden kann? Ich würde einfach den kompletten Code in eine neue Klasse übernehmen und dann in meiner bisherigen Klasse ein Objekt der Klasse HeatMap erzeugen (oder nicht?).. und dann?



DAS ist jetzt eine Frage, mit der man was anfangen kann 

Du speicherst den Code als HeatMap.java ab. Wenn Du sie in ein Paket verschiebst, musst Du natürlich die package-Zeile anpassen. Ansonsten kannst Du das Teil wie jede andere Komponente auch verwenden.


----------



## iltisjan (25. Jul 2018)

Spätestens aus der Özil Affäre habe ich gelernt, man muss auch ein wenig selbstkritisch sein. Also OK, meine Frage war nicht so klar gestellt, das gebe ich zu. Aber man kann trotzdem normal antworten finde ich.
Naja, Schwamm drüber.



mihe7 hat gesagt.:


> Du speicherst den Code als HeatMap.java ab. Wenn Du sie in ein Paket verschiebst, musst Du natürlich die package-Zeile anpassen. Ansonsten kannst Du das Teil wie jede andere Komponente auch verwenden.


Danke für die Antwort, damit konnte ich schonmal was anfangen.

Das habe ich gemacht.
Dann habe ich in meiner anderen Klasse (im selben Paket) ein Objekt der Klasse HeatMap erzeugt, wobei data wie gesagt ein double[8][12] ist:

data=writeToExcel(blank);
Color[] colors=new Color[2];
colors[0]=Color.yellow;
colors[1]=Color.red;
HeatMap hm = new HeatMap(data, false, colors);

In der HeatMap.java habe ich außerdem in der Funktion drawData() folgenden Code ergänzt:

File out2 = new File("Heat.png");
        try {
            ImageIO.write(bufferedImage, "png", out2);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

weil ich die Ausgabe gerne in einer Datei haben möchte.

Was ich bekomme ist ein winziges .png File. Das ist ein winziges rechteckiges gelbes Rechteck mit einem kleinen roten Punkt in der Mitte. Ich hätte das gerne in: größer, mit Gradient, mit X- und Y-Achsen-Beschriftung.
Außerdem müssten die Punkte anders verteilt sein. Das sind die Daten die in die HeatMap sollen:
Ist jetzt hier schwer zu erkenne, aber die roten markierten zahlen sollten deutlich herausstechen...und nicht nur ein Punkt.


0.0474 0.0475 0.047 0.999 0.0468 0.0468 0.0468 0.047 0.0471 0.0467 0.0472 0.0481
0.0333 0.1808 0.3116 1.114 0.2361 0.4748 0.1035 0.1822 0.0885 0.0898 0.0954 0.047
0.0968 0.2463 0.1723 0.877 0.2801 0.5383 0.1014 0.0774 0.1286 0.0869 0.0888 0.0468
0.0984 0.2303 10 0.887 0.2249 0.2569 50  0.0752 0.0775 80 0.0876 0.0466
0.1367 0.0805 0.409 1.002 0.3857 0.5032 0.0951 0.0839 0.0861 0.1636 0.0923 0.047
 250 0.389 0.1696 0.987 0.1472 0.6806 0.157 0.0834 0.5197 0.143 0.1894 0.0467
0.0356 0.4484 0.3521 0.956 0.5312 0.5037 0.4991 0.5523 0.0966 0.146 0.0889 0.047
0.0459 0.0467 0.0468 0.899 0.0465 120 0.0465 0.046 0.047 0.0466 0.0467 0.0464

Ich dachte ich könnte den Titel, X- und Y-Achse in den Zeilen 29-31 definieren, aber das klappt nicht.
Was mache ich falsch?

Am Liebsten wäre mir eine fertige Komponente, die man einfach mit seinen Daten befüttert und die HeatMap als Datei ausgibt. Eine Beschriftung sollte auch dazu, das fehlt mir auch momentan bei der Ausgabe...


----------



## mihe7 (25. Jul 2018)

```
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Test {


    public static void main(String[] args) throws Exception {
        double[][] data = new double[10][10];
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                data[i][j] = Math.random();
            }
        }

        Color[] colors=new Color[2];
        colors[0]=Color.yellow;
        colors[1]=Color.red;
        HeatMap hm = new HeatMap(data, false, colors);
        hm.setBounds(0,0,600,400);
        BufferedImage img = new BufferedImage(600, 400, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        hm.paintComponent(g2);
        g2.dispose();

        ImageIO.write(img, "png", new File("heat.png"));
    }
}
```


----------



## iltisjan (25. Jul 2018)

mihe7 hat gesagt.:


> ```
> import java.awt.*;
> import java.awt.image.*;
> import java.io.*;
> ...



Danke. Das sieht schon besser aus. Nur habe ich jetzt noch keinen richtigen Gradienten. Ich habe also nur gelbe und rote Felder, aber nichts dazwischen. Ich habe mir das so gedacht, dass kleine Zahlen gelb sind, mittelgroße orange und hohe Zahlen dann rot.
Wenn ich aber nur 2 Farben übergebe (gelb und rot) dann bekomme ich nur einen einzigen roten Punkt, egal welche Daten man eingibt... Wenn ich 3 Farben übergebe, dann bekomme ich mehrere rote und gelbe Punkte und einen blauen Punkt.. Komisch. Das Verstehe ich noch nicht so wirklich.

Was mir noch fehlt ist die Achsen- und Titelbeschriftung. Kann mir einer sagen, wo ich diese definiere?


----------



## mihe7 (25. Jul 2018)

```
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Test {
    public static void main(String[] args) throws Exception {
        double[][] data = new double[100][100];
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                data[i][j] = Math.random()*1000;
            }
        }
        HeatMap hm = new HeatMap(data, false, Gradient.createGradient(Color.yellow, Color.red, 100));
        hm.setCoordinateBounds(0, data.length, 0, 1000);
        hm.setDrawXTicks(true);
        hm.setDrawYTicks(true);
        hm.setDrawXAxisTitle(true);
        hm.setDrawYAxisTitle(true);
        hm.setDrawTitle(true);
        hm.setTitle("My Heat Map");
        hm.setXAxisTitle("The x-axis");
        hm.setYAxisTitle("The y-axis");
        hm.setDrawLegend(true);
        hm.setBounds(0,0,600,400);
        BufferedImage img = new BufferedImage(600, 400, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();
        hm.paintComponent(g2);
        g2.dispose();

        ImageIO.write(img, "png", new File("heat.png"));
    }
}
```

Doku gibt es unter https://www.mbeckler.org/heatMap/javadoc/index.html?HeatMap.html

Ergebnis: s. Anhang.


----------



## iltisjan (25. Jul 2018)

mihe7 hat gesagt.:


> ```
> import java.awt.*;
> import java.awt.image.*;
> import java.io.*;
> ...




Ich möchte mich herzlich dafür bedanken... Ich habe das auch schon gesehen, aber hätte nicht gedacht, dass es so einfach geht.
Vielen Dank.


----------

