Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
core
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Requirements
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
minerva
core
Merge requests
!1377
Resolve "automatic scale generator for data overlays"
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Resolve "automatic scale generator for data overlays"
205-automatic-scale-generator-for-data-overlays
into
master
Overview
0
Commits
3
Pipelines
2
Changes
14
Merged
Piotr Gawron
requested to merge
205-automatic-scale-generator-for-data-overlays
into
master
3 years ago
Overview
0
Commits
3
Pipelines
2
Changes
14
Expand
Closes
#205 (closed)
,
#1061 (closed)
Edited
3 years ago
by
Piotr Gawron
0
0
Merge request reports
Compare
master
master (base)
and
latest version
latest version
15d4e206
3 commits,
3 years ago
14 files
+
7074
−
114
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
14
Search (e.g. *.vue) (Ctrl+P)
converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/LegendGenerator.java
0 → 100644
+
228
−
0
Options
package
lcsb.mapviewer.converter.graphics
;
import
java.awt.Color
;
import
java.awt.Font
;
import
java.awt.Graphics2D
;
import
java.awt.geom.Rectangle2D
;
import
java.awt.image.BufferedImage
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
javax.imageio.ImageIO
;
import
lcsb.mapviewer.commands.ColorExtractor
;
import
lcsb.mapviewer.common.exception.NotImplementedException
;
import
lcsb.mapviewer.model.overlay.DataOverlay
;
import
lcsb.mapviewer.model.overlay.DataOverlayEntry
;
import
lcsb.mapviewer.model.overlay.GeneVariantDataOverlayEntry
;
import
lcsb.mapviewer.model.overlay.GenericDataOverlayEntry
;
public
class
LegendGenerator
{
private
static
final
int
WIDTH
=
800
;
private
static
final
int
HEIGHT
=
300
;
private
static
final
int
COLOR_HEIGHT
=
100
;
private
static
final
int
MARGIN
=
100
;
BufferedImage
getImage
(
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
{
BufferedImage
result
=
new
BufferedImage
(
WIDTH
,
HEIGHT
,
BufferedImage
.
TYPE_INT_ARGB
);
Graphics2D
graphics
=
result
.
createGraphics
();
Set
<
Class
<?
extends
DataOverlayEntry
>>
entryTypes
=
new
HashSet
<>();
for
(
DataOverlayEntry
entry
:
overlay
.
getEntries
())
{
entryTypes
.
add
(
entry
.
getClass
());
}
if
(
entryTypes
.
size
()
!=
1
)
{
if
(
entryTypes
.
size
()
<
1
)
{
generateMessageLegend
(
"No entries found"
,
graphics
);
}
else
{
generateMessageLegend
(
"Legend not available for mixed entry types"
,
graphics
);
}
}
else
{
Class
<?
extends
DataOverlayEntry
>
type
=
entryTypes
.
iterator
().
next
();
if
(
type
==
GenericDataOverlayEntry
.
class
)
{
generateGenericLegend
(
graphics
,
overlay
,
colorExtractor
);
}
else
if
(
type
==
GeneVariantDataOverlayEntry
.
class
)
{
generateGeneticLegend
(
graphics
,
overlay
,
colorExtractor
);
}
else
{
generateMessageLegend
(
"Legend not available for overlay type: "
+
type
.
getSimpleName
(),
graphics
);
}
}
return
result
;
}
void
generateMessageLegend
(
final
String
message
,
final
Graphics2D
graphics
)
{
Color
oldColor
=
graphics
.
getColor
();
Font
oldFont
=
graphics
.
getFont
();
graphics
.
setColor
(
Color
.
BLACK
);
graphics
.
setFont
(
new
Font
(
Font
.
SANS_SERIF
,
0
,
24
));
graphics
.
drawString
(
message
,
MARGIN
+
COLOR_HEIGHT
+
50
,
MARGIN
+
COLOR_HEIGHT
/
2
);
graphics
.
setColor
(
oldColor
);
graphics
.
setFont
(
oldFont
);
}
void
generateGeneticLegend
(
final
Graphics2D
graphics
,
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
{
Color
oldColor
=
graphics
.
getColor
();
Font
oldFont
=
graphics
.
getFont
();
Map
<
Integer
,
Color
>
colors
=
new
HashMap
<>();
for
(
DataOverlayEntry
entry
:
overlay
.
getEntries
())
{
colors
.
put
(((
GeneVariantDataOverlayEntry
)
entry
).
getGeneVariants
().
size
(),
colorExtractor
.
getNormalizedColor
(
entry
));
}
int
width
=
WIDTH
-
2
*
MARGIN
;
double
elementWidth
=
((
double
)
width
)
/
(
double
)
(
colors
.
size
());
List
<
Integer
>
counters
=
new
ArrayList
<>(
colors
.
keySet
());
Collections
.
sort
(
counters
);
for
(
int
i
=
0
;
i
<
counters
.
size
();
i
++)
{
int
count
=
counters
.
get
(
i
);
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
+
i
*
elementWidth
,
MARGIN
,
elementWidth
,
COLOR_HEIGHT
);
graphics
.
setColor
(
colors
.
get
(
count
));
graphics
.
fill
(
rectangle
);
}
graphics
.
setFont
(
new
Font
(
Font
.
SANS_SERIF
,
0
,
18
));
graphics
.
setColor
(
Color
.
BLACK
);
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
,
MARGIN
,
WIDTH
-
2
*
MARGIN
,
COLOR_HEIGHT
);
graphics
.
draw
(
rectangle
);
graphics
.
drawString
(
"Number of gene variants:"
,
MARGIN
,
MARGIN
/
2
);
int
labelCount
=
Math
.
min
(
10
,
counters
.
size
());
for
(
int
i
=
0
;
i
<=
labelCount
;
i
++)
{
int
selected
=
i
*
(
counters
.
size
()
-
1
)
/
labelCount
;
int
x
=
(
int
)
(
MARGIN
+
(
selected
+
0.5
)
*
elementWidth
);
graphics
.
drawLine
(
x
,
MARGIN
-
10
,
x
,
MARGIN
);
graphics
.
drawString
(
String
.
format
(
"%d"
,
counters
.
get
(
selected
)),
x
,
MARGIN
-
20
);
}
graphics
.
setColor
(
oldColor
);
graphics
.
setFont
(
oldFont
);
}
void
generateGenericLegend
(
final
Graphics2D
graphics
,
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
{
boolean
byValue
=
false
;
boolean
byColor
=
false
;
for
(
DataOverlayEntry
entry
:
overlay
.
getEntries
())
{
GenericDataOverlayEntry
genericDataOverlayEntry
=
(
GenericDataOverlayEntry
)
entry
;
if
(
genericDataOverlayEntry
.
getValue
()
!=
null
)
{
byValue
=
true
;
}
if
(
genericDataOverlayEntry
.
getColor
()
!=
null
)
{
byColor
=
true
;
}
}
if
(
byValue
&&
byColor
)
{
throw
new
NotImplementedException
();
}
else
if
(
byValue
)
{
generateGenericLegendByValue
(
graphics
,
overlay
,
colorExtractor
);
}
else
if
(
byColor
)
{
generateGenericLegendByColor
(
graphics
,
overlay
,
colorExtractor
);
}
else
{
generateGenericLegendBySimple
(
graphics
,
overlay
,
colorExtractor
);
}
}
void
generateGenericLegendBySimple
(
final
Graphics2D
graphics
,
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
{
Color
oldColor
=
graphics
.
getColor
();
Font
oldFont
=
graphics
.
getFont
();
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
,
MARGIN
,
COLOR_HEIGHT
,
COLOR_HEIGHT
);
graphics
.
setColor
(
colorExtractor
.
getSimpleColor
());
graphics
.
fill
(
rectangle
);
graphics
.
setColor
(
Color
.
BLACK
);
graphics
.
draw
(
rectangle
);
graphics
.
setFont
(
new
Font
(
Font
.
SANS_SERIF
,
0
,
24
));
graphics
.
drawString
(
"Element present on the map"
,
MARGIN
+
COLOR_HEIGHT
+
50
,
MARGIN
+
COLOR_HEIGHT
/
2
);
graphics
.
setColor
(
oldColor
);
graphics
.
setFont
(
oldFont
);
}
void
generateGenericLegendByColor
(
final
Graphics2D
graphics
,
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
{
Color
oldColor
=
graphics
.
getColor
();
Font
oldFont
=
graphics
.
getFont
();
Set
<
Color
>
colorSet
=
new
HashSet
<>();
for
(
DataOverlayEntry
entry
:
overlay
.
getEntries
())
{
colorSet
.
add
(((
GenericDataOverlayEntry
)
entry
).
getColor
());
}
List
<
Color
>
colors
=
new
ArrayList
<>(
colorSet
);
colors
.
sort
(
new
Comparator
<
Color
>()
{
@Override
public
int
compare
(
final
Color
o1
,
final
Color
o2
)
{
return
o1
.
getRGB
()
-
o2
.
getRGB
();
}
});
double
elementWidth
=
((
double
)
(
WIDTH
-
2
*
MARGIN
))
/
(
double
)
colors
.
size
();
for
(
int
i
=
0
;
i
<
colors
.
size
();
i
++)
{
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
+
i
*
elementWidth
,
MARGIN
,
elementWidth
,
COLOR_HEIGHT
);
graphics
.
setColor
(
colors
.
get
(
i
));
graphics
.
fill
(
rectangle
);
}
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
,
MARGIN
,
WIDTH
-
2
*
MARGIN
,
COLOR_HEIGHT
);
graphics
.
setColor
(
Color
.
BLACK
);
graphics
.
draw
(
rectangle
);
graphics
.
setFont
(
new
Font
(
Font
.
SANS_SERIF
,
0
,
24
));
graphics
.
drawString
(
"Entries have custom colors defined:"
,
MARGIN
,
MARGIN
-
10
);
graphics
.
setColor
(
oldColor
);
graphics
.
setFont
(
oldFont
);
}
void
generateGenericLegendByValue
(
final
Graphics2D
graphics
,
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
{
Color
oldColor
=
graphics
.
getColor
();
Font
oldFont
=
graphics
.
getFont
();
int
width
=
WIDTH
-
2
*
MARGIN
;
for
(
int
i
=
0
;
i
<
width
;
i
++)
{
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
+
i
,
MARGIN
,
1
,
COLOR_HEIGHT
);
GenericDataOverlayEntry
entry
=
new
GenericDataOverlayEntry
();
entry
.
setValue
(((
double
)
(
i
-
width
/
2
))
/
(
double
)
(
width
/
2.0
));
graphics
.
setColor
(
colorExtractor
.
getNormalizedColor
(
entry
));
graphics
.
fill
(
rectangle
);
}
graphics
.
setColor
(
Color
.
BLACK
);
graphics
.
setFont
(
new
Font
(
Font
.
SANS_SERIF
,
0
,
18
));
for
(
double
val
=
-
1.0
;
val
<=
1.0
;
val
+=
0.2
)
{
int
x
=
(
int
)
(
WIDTH
/
2
+
val
*
width
/
2
);
graphics
.
drawLine
(
x
,
MARGIN
-
10
,
x
,
MARGIN
);
graphics
.
drawString
(
String
.
format
(
"%.1f"
,
val
),
x
,
MARGIN
-
20
);
}
Rectangle2D
rectangle
=
new
Rectangle2D
.
Double
(
MARGIN
,
MARGIN
,
WIDTH
-
2
*
MARGIN
,
COLOR_HEIGHT
);
graphics
.
draw
(
rectangle
);
graphics
.
setColor
(
oldColor
);
graphics
.
setFont
(
oldFont
);
}
public
byte
[]
generate
(
final
DataOverlay
overlay
,
final
ColorExtractor
colorExtractor
)
throws
IOException
{
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
ImageIO
.
write
(
getImage
(
overlay
,
colorExtractor
),
"PNG"
,
baos
);
return
baos
.
toByteArray
();
}
public
void
savetToPng
(
final
DataOverlay
overlay
,
final
ColorExtractor
extractor
,
final
String
filename
)
throws
IOException
{
FileOutputStream
fos
=
new
FileOutputStream
(
new
File
(
filename
));
ImageIO
.
write
(
getImage
(
overlay
,
extractor
),
"PNG"
,
fos
);
}
}
Loading