matplotlib - set font to Times New Roman - matplotlib

I want to use Times New Roman font with my matplotlib plots. I'm currently using matplotlib-3.5.1 and I have fonttools-4.28.5 installed. However, when I try:
plt.rcParams["font.family"] = "Times New Roman"
The font doesn't change. I then found a recommendation to instead try:
plt.rcParams["font.family"] = "DejaVu Serif"
plt.rcParams["font.serif"] = ["Times New Roman"]
This also had no effect. What am I doing wrong and how do I fix it?
I already looked at other posts e.g. 1, 2 to no avail.
Edit: Following this post, it appears that matplotlib doesn't have Times New Roman?
['C059', 'C059', 'C059', 'C059', 'D050000L', 'DejaVu LGC Sans Mono', 'DejaVu LGC Sans Mono', 'DejaVu LGC Sans Mono', 'DejaVu LGC Sans Mono', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans', 'DejaVu Sans Display', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Sans Mono', 'DejaVu Serif', 'DejaVu Serif', 'DejaVu Serif', 'DejaVu Serif', 'DejaVu Serif Display', 'Liberation Mono', 'Liberation Mono', 'Liberation Mono', 'Liberation Mono', 'Nimbus Mono PS', 'Nimbus Mono PS', 'Nimbus Mono PS', 'Nimbus Mono PS', 'Nimbus Roman', 'Nimbus Roman', 'Nimbus Roman', 'Nimbus Roman', 'Nimbus Sans', 'Nimbus Sans', 'Nimbus Sans', 'Nimbus Sans', 'Nimbus Sans Narrow', 'Nimbus Sans Narrow', 'Nimbus Sans Narrow', 'Nimbus Sans Narrow', 'P052', 'P052', 'P052', 'P052', 'STIX', 'STIX', 'STIX', 'STIX', 'STIX Math', 'STIXGeneral', 'STIXGeneral', 'STIXGeneral', 'STIXGeneral', 'STIXNonUnicode', 'STIXNonUnicode', 'STIXNonUnicode', 'STIXNonUnicode', 'STIXSizeFiveSym', 'STIXSizeFourSym', 'STIXSizeFourSym', 'STIXSizeOneSym', 'STIXSizeOneSym', 'STIXSizeThreeSym', 'STIXSizeThreeSym', 'STIXSizeTwoSym', 'STIXSizeTwoSym', 'URW Bookman', 'URW Bookman', 'URW Bookman', 'URW Bookman', 'URW Gothic', 'URW Gothic', 'URW Gothic', 'URW Gothic', 'Z003', 'cmb10', 'cmex10', 'cmmi10', 'cmr10', 'cmss10', 'cmsy10', 'cmtt10']

Following https://matplotlib.org/stable/gallery/text_labels_and_annotations/font_family_rc_sgskip.html?highlight=font#configuring-the-font-family, this should work:
plt.rcParams["font.family"] = "serif"
plt.rcParams["font.serif"] = ["Times New Roman"]

Related

Mapbox GL JS markers go outside map

When the map loads, all of the burgers / markers are visible (I intentionally set the zoom to account for all the burgers in the area.) For some reason, when I pan around on the map or zoom in/out, the burgers / markers follow the pan and escape the map's bounds / edges. I tried using default markers and removing the script that programmatically adds popups to the markers. I'll post some relevant code here.
You can see that the burgers not only show up outside the map, but stretch the width of the window as they move.
HTML
<div class="content">
<div class="story-list"></div>
<div class="story-map">
<div class="story-map-container" id="story-map-container"></div>
</div>
</div>
CSS
.content {
padding: 6.5%;
width: 87%;
background-image: url("../media/images/temp-gradient-low.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
/* story-list */
.story-list {
display: inline-block;
position: relative;
width: 66%;
z-index: 1;
vertical-align: top;
font-size: 0;
padding-bottom: 1%;
}
/* story-map */
.story-map { /* using id='' in order to override the position set by mapbox*/
/*background-color: white;*/
display: inline-block;
position: sticky;
top: 0;
width: 33%;
height: 100vh;
/*padding-left: 2.5%;*/
z-index: 0;
vertical-align: top;
/*float: right;*/
}
#story-map-container {
background-color: lightgreen;
width: 100%;
/*margin-left: 2.5%;*/
height: 100%;
overflow: visible;
}
.mapboxgl-map {
position: absolute;
overflow: visible;
}
.mapboxgl-marker {
background-image: url("../media/icons/burger-marker.png");
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
.mapboxgl-popup {
max-width: 200px;
}
.mapboxgl-popup-content {
text-align: center;
}
JS
var map = null;
function initMapbox() {
mapboxgl.accessToken = 'pk.eyJ1IjoiZGFua3NreSIsImEiOiJjanNmbTA0YWkwdWx5NDNtdG1idHpwNTE3In0.Y16huX7_p26tsDlcJTWWFQ';
map = new mapboxgl.Map({
container: 'story-map-container',
style: 'mapbox://styles/mapbox/streets-v11',
zoom: 10,
center: [-118.338604, 34.083480]
});
}
function parseStuff() {
const lorem = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.`;
const list = Array.from({length: 10}, (x,i) => {
return {
name: 'The Burger Place',
address: '123 Yumyum Hwy',
coordinates: {lat: 34.083480 + Math.random() * 0.1, lng: -118.348604 + Math.random() * 0.1},
phoneNumber: '1-123-456-7890',
website: {
text: 'BURGERSITE',
url: 'http://google.com'
},
description: 'A happy place for people who eat meat.',
review: lorem.substring(0, lorem.length * 0.6)
};
});
console.log(list);
list.forEach((element, index) => {
var customMarker = document.createElement('div');
customMarker.className = 'mapboxgl-marker';
customMarker.onclick = (e) => {
map.panTo([element.coordinates.lng, element.coordinates.lat]);
window.location.hash = `burger-place-${index}`
};
var popupContent = `${element.name}<br />${element.phoneNumber}`
var marker = new mapboxgl.Marker(customMarker)
.setLngLat([element.coordinates.lng, element.coordinates.lat]);
marker.setPopup(new mapboxgl.Popup({ offset: 25 }).setHTML(popupContent))
.addTo(map);
})
$('.story-list').html(componentList);
}
window.onload = () => {
initMapbox();
parseStuff();
};
.story-map {
overflow: hidden;
//...
}
fixes your issues. Though I'm also somewhat confused as to why mapbox draws the markers beyond its canvas.

Dynamically close the table row if row text Goes to next page in pdf using xsl fo style sheet

I have a requirement that , "the content which i have to display in a table comes dynamically, if it's goes to next page i have to close the table row and open new row in next page of PDF.
I am using XSL style sheet and FOP_0_95.
sample code which i have used to display table in PDF.
<fo:table border="0.0px solid black" width="100%">
<fo:table-column column-width="100%" />
<fo:table-body>
<fo:table-row>
<fo:table-cell border="0.0px solid black" padding-before="0.5cm">
<fo:block font-family="Times Roman" text-align="left" font-size="9pt">
-- content goes here -- Row1
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell border="0.0px solid black" text-align="left" padding-before="0.2cm">
<fo:block font-family="Times Roman" text-align="left" font-size="9pt">
-- content goes here -- Row2
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
for suppose , if row1 content goes to next page , then i have to close the row and open new row in next page.
Please provide me the solution in XSL.
Thanks in Advance.
Venkat.
This is likely what you want ...
<fo:table width="50%" border="1px solid black" border-before-width.conditionality="retain" border-after-width.conditionality="retain">
<fo:table-body>
<fo:table-row>
<fo:table-cell border="1px solid black">
<fo:block font-family="Times Roman" text-align="left" font-size="9pt">
Tation luptatum nobis vero illum lorem sed sadipscing ipsum ipsum feugait sea dolor ipsum ut sea. Justo possim at et ipsum dolor et eum ullamcorper aliquyam rebum dolor ea labore hendrerit tempor vero nostrud. Et lorem est magna eos et et eos est. Quod eos erat nonummy sed vero praesent justo sadipscing nulla stet enim tincidunt vero at et qui aliquam. Et accusam consetetur consetetur consetetur kasd wisi ipsum no dolores tempor aliquyam commodo. Ad clita takimata molestie stet stet iriure at duo magna. Labore duis eros aliquyam. Nulla sed dolores lorem eirmod. Ex erat invidunt dolores amet no sadipscing volutpat sanctus vero eirmod et clita clita duo luptatum ut invidunt.
</fo:block>
</fo:table-cell>
</fo:table-row>
...
Drawing a border on the table and retaining border-before and border-after will draw the border at the page break when the cell splits across pages, like in the image below:

PhantomJS font rendering problems when generating PDF

I am using 2.0 build of PhantomJS and I render my HTML's to PDF. However, my fonts were looking very narrow and like glued together. I tried to give proper letter-spacing property to elements but then I realized that it is not a css or font issue, but an issue that is specific when creating PDF. I have no problem rendering to PNG.
So here is the original html that I use (I removed html tags, it was causing problems with the editor). I created the font-face with fontsquirrel using arial.ttf from Windows fonts folder.
<head>
<title>Trial</title>
<style>
#font-face {
font-family: 'arialregular';
src: url('arial-webfont.woff2') format('woff2'),
url('arial-webfont.woff') format('woff'),
url('arial-webfont.ttf') format('truetype');
font-weight: normal;
font-style: normal;
letter-spacing: normal;
}
body {
color: #000000;
font-family: arialregular, sans-serif;
margin-left: 15px;
margin-top: 15px;
font-size: 9pt;
}
</style>
</head>
<body>
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
</body>
I use rasterize.js to create png and pdf. Here is the png result, which is expected and have no problems.
phantomjs.exe rasterize.js my.html my.png a4
Arial font is rendered correctly. When I generate pdf using
phantomjs.exe rasterize.js my.html my.pdf a4
it generates the pdf without any error. And here is how it looks like just after opening it on Adobe PDF (not reader). When clicked to the container notice that there is no font shown.
When I click in the element to edit it, but without doing any edit and just putting the cursor, it shows me an embed font.
Looks like it tries to embed the font to the pdf, but it fails as the size of PDF is 6kb when font's is about half a MB.
When I commit to edit, like writing a space etc, it shows me the following error and falls back to Minion Pro.
You will be asking why I do not use just Arial as it is available, and I did all those above to debug the issue: Same happens to Arial. So when I change the css from above to this:
body {
color: #000000;
font-family: "Arial", sans-serif;
margin-left: 15px;
margin-top: 15px;
font-size: 9pt;
width: 21.5cm;
}
the PNG renders the same, without problems. The PDF, however, shows Arial when clicked, but when I try to edit it gives the same error saying Arial is not available and it falls back to Minion Pro again.
How can I fix this problem?

Bootstrap 3 tabs with 100% height

I don't understand why the page doesn't fit the screen and why a scroll bar is added to the page.
Here is the code:
#side {
width: 100px;
height: 100px;
min-height: 100%;
min-width: 100%;
}
.list {
height: 100%;
width: 100%;
overflow: auto;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.fill {
padding: 0;
min-height: 100%;
height: 100%;
width: 100%;
min-width: 100%;
}
.container-side {
padding: 5px 10px 5px 5px;
min-height: 100%;
height: 100%;
}
.tablist {
min-height: 100%;
height: 100%;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div class="container-fluid fill">
<div class="row-fluid fill">
<div class="col-xs-12 col-md-4 container-side">
<div id="side">
<ul id="tabs" class="nav nav-tabs hidden-print">
<li class="active">Tab1</span></li>
<li>Tab2</span></li>
</ul>
<div id="tab-1" class="tablist container-fluid tab-pane fade in active">
<div class="list">
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
Cognitis enim pilatorum caesorumque funeribus nemo deinde ad has stationes appulit navem, sed ut Scironis praerupta letalia declinantes litoribus Cypriis contigui navigabant, quae Isauriae scopulis sunt controversa.
Alii nullo quaerente vultus severitate adsimulata patrimonia sua in inmensum extollunt, cultorum ut puta feracium multiplicantes annuos fructus, quae a primo ad ultimum solem se abunde iactitant possidere, ignorantes profecto maiores suos, per quos ita magnitudo Romana porrigitur, non divitiis eluxisse sed per bella saevissima, nec opibus nec victu nec indumentorum vilitate gregariis militibus discrepantes opposita cuncta superasse virtute.
Illud tamen te esse admonitum volo, primum ut qualis es talem te esse omnes existiment ut, quantum a rerum turpitudine abes, tantum te a verborum libertate seiungas; deinde ut ea in alterum ne dicas, quae cum tibi falso responsa sint, erubescas. Quis est enim, cui via ista non pateat, qui isti aetati atque etiam isti dignitati non possit quam velit petulanter, etiamsi sine ulla suspicione, at non sine argumento male dicere? Sed istarum partium culpa est eorum, qui te agere voluerunt; laus pudoris tui, quod ea te invitum dicere videbamus, ingenii, quod ornate politeque dixisti.
Illud tamen te esse admonitum volo, primum ut qualis es talem te esse omnes existiment ut, quantum a rerum turpitudine abes, tantum te a verborum libertate seiungas; deinde ut ea in alterum ne dicas, quae cum tibi falso responsa sint, erubescas. Quis est enim, cui via ista non pateat, qui isti aetati atque etiam isti dignitati non possit quam velit petulanter, etiamsi sine ulla suspicione, at non sine argumento male dicere? Sed istarum partium culpa est eorum, qui te agere voluerunt; laus pudoris tui, quod ea te invitum dicere videbamus, ingenii, quod ornate politeque dixisti.
Illud tamen te esse admonitum volo, primum ut qualis es talem te esse omnes existiment ut, quantum a rerum turpitudine abes, tantum te a verborum libertate seiungas; deinde ut ea in alterum ne dicas, quae cum tibi falso responsa sint, erubescas. Quis est enim, cui via ista non pateat, qui isti aetati atque etiam isti dignitati non possit quam velit petulanter, etiamsi sine ulla suspicione, at non sine argumento male dicere? Sed istarum partium culpa est eorum, qui te agere voluerunt; laus pudoris tui, quod ea te invitum dicere videbamus, ingenii, quod ornate politeque dixisti.
</p>
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
Cognitis enim pilatorum caesorumque funeribus nemo deinde ad has stationes appulit navem, sed ut Scironis praerupta letalia declinantes litoribus Cypriis contigui navigabant, quae Isauriae scopulis sunt controversa.
</p>
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
</p>
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
Cognitis enim pilatorum caesorumque funeribus nemo deinde ad has stationes appulit navem, sed ut Scironis praerupta letalia declinantes litoribus Cypriis contigui navigabant, quae Isauriae scopulis sunt controversa.
Alii nullo quaerente vultus severitate adsimulata patrimonia sua in inmensum extollunt, cultorum ut puta feracium multiplicantes annuos fructus, quae a primo ad ultimum solem se abunde iactitant possidere, ignorantes profecto maiores suos, per quos ita magnitudo Romana porrigitur, non divitiis eluxisse sed per bella saevissima, nec opibus nec victu nec indumentorum vilitate gregariis militibus discrepantes opposita cuncta superasse virtute.
</p>
</div>
</div>
<div id="tab-2" class="tablist container-fluid tab-pane fade">
</div>
</div>
</div>
</div>
</div>
As all the div are 100% relative I await to not have a scrolled page.
This is not the case. Where is the issue ?
Thanks.
there are so many things wrong with the example that you have posted. Allow me to list them
You have not included jquery-ui library. jquery tabs is a part of jquery-ui library and not jQuery
Your both tab headers point to same tab i.e. <a href="#tab-1", where as it should be #tab-1 for first and #tab-2 for another
Your entire custom css is just too much. you don't need any of it to do what you want to.
you need to initialize your tabs i.e call the jQuery ui plugin on the tab container
Basically you have abused the height and min-height property. Anyhow I've simplified everything for you. Remove your entire custom css (the ones pasted here in your question) and use just these:
.tablist{
height:87%;/*fallback if calc not available*/
height:calc(100% - 5em);
overflow-y:auto;
}
.fill{
padding: 0;
}
.container-side {
padding: 5px 10px 5px 5px;
}
notice how calc property has been used in the css class .tablist.
Now other than that, you must include following libraries
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
notice a new js library has been added after jQuery and bootstrap library
and that is jquery-ui.js
also, you must initialize your tabs, so at the end of the body, you must do below
<script>
$(document).ready(function(){
$('#side').tabs();
});
</script>
rest assured, it should work perfectly
Eureka hereafter is the solution.
To take into account of nav-tab header (42px), the size of the tab content should be recalculated. So I use :
.tab-content {
overflow: auto;
height: calc(100vh - 42px);
height: -webkit-calc(100vh - 42px);
height: -moz-calc(100vh - 42px);
}
Otherwise all the heights are deduced from body (viewport) by inheritance:
.fill, .container-side {
height: inherit;
}
See the complete code below:
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.fill, .container-side {
height: inherit;
}
.tab-content {
overflow: auto;
height: calc(100vh - 42px);
height: -webkit-calc(100vh - 42px);
height: -moz-calc(100vh - 42px);
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div class="container-fluid fill">
<div class="row-fluid fill">
<div class="col-xs-12 col-md-4 container-side">
<ul class="nav nav-tabs">
<li class="active">Tab1</span></li>
<li>Tab2</span></li>
</ul>
<div id="side" class="tab-content">
<div id="tab-1" class="tablist container-fluid tab-pane fade in active">
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
Cognitis enim pilatorum caesorumque funeribus nemo deinde ad has stationes appulit navem, sed ut Scironis praerupta letalia declinantes litoribus Cypriis contigui navigabant, quae Isauriae scopulis sunt controversa.
Alii nullo quaerente vultus severitate adsimulata patrimonia sua in inmensum extollunt, cultorum ut puta feracium multiplicantes annuos fructus, quae a primo ad ultimum solem se abunde iactitant possidere, ignorantes profecto maiores suos, per quos ita magnitudo Romana porrigitur, non divitiis eluxisse sed per bella saevissima, nec opibus nec victu nec indumentorum vilitate gregariis militibus discrepantes opposita cuncta superasse virtute.
Illud tamen te esse admonitum volo, primum ut qualis es talem te esse omnes existiment ut, quantum a rerum turpitudine abes, tantum te a verborum libertate seiungas; deinde ut ea in alterum ne dicas, quae cum tibi falso responsa sint, erubescas. Quis est enim, cui via ista non pateat, qui isti aetati atque etiam isti dignitati non possit quam velit petulanter, etiamsi sine ulla suspicione, at non sine argumento male dicere? Sed istarum partium culpa est eorum, qui te agere voluerunt; laus pudoris tui, quod ea te invitum dicere videbamus, ingenii, quod ornate politeque dixisti.
Alii nullo quaerente vultus severitate adsimulata patrimonia sua in inmensum extollunt, cultorum ut puta feracium multiplicantes annuos fructus, quae a primo ad ultimum solem se abunde iactitant possidere, ignorantes profecto maiores suos, per quos ita magnitudo Romana porrigitur, non divitiis eluxisse sed per bella saevissima, nec opibus nec victu nec indumentorum vilitate gregariis militibus discrepantes opposita cuncta superasse virtute.
Illud tamen te esse admonitum volo, primum ut qualis es talem te esse omnes existiment ut, quantum a rerum turpitudine abes, tantum te a verborum libertate seiungas; deinde ut ea in alterum ne dicas, quae cum tibi falso responsa sint, erubescas. Quis est enim, cui via ista non pateat, qui isti aetati atque etiam isti dignitati non possit quam velit petulanter, etiamsi sine ulla suspicione, at non sine argumento male dicere? Sed istarum partium culpa est eorum, qui te agere voluerunt; laus pudoris tui, quod ea te invitum dicere videbamus, ingenii, quod ornate politeque dixisti.
</p>
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
Cognitis enim pilatorum caesorumque funeribus nemo deinde ad has stationes appulit navem, sed ut Scironis praerupta letalia declinantes litoribus Cypriis contigui navigabant, quae Isauriae scopulis sunt controversa.
</p>
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
</p>
<p>
Illud tamen clausos vehementer angebat quod captis navigiis, quae frumenta vehebant per flumen, Isauri quidem alimentorum copiis adfluebant, ipsi vero solitarum rerum cibos iam consumendo inediae propinquantis aerumnas exitialis horrebant.
Cognitis enim pilatorum caesorumque funeribus nemo deinde ad has stationes appulit navem, sed ut Scironis praerupta letalia declinantes litoribus Cypriis contigui navigabant, quae Isauriae scopulis sunt controversa.
Alii nullo quaerente vultus severitate adsimulata patrimonia sua in inmensum extollunt, cultorum ut puta feracium multiplicantes annuos fructus, quae a primo ad ultimum solem se abunde iactitant possidere, ignorantes profecto maiores suos, per quos ita magnitudo Romana porrigitur, non divitiis eluxisse sed per bella saevissima, nec opibus nec victu nec indumentorum vilitate gregariis militibus discrepantes opposita cuncta superasse virtute.
</p>
</div>
<div id="tab-2" class="tablist container-fluid tab-pane fade">
...
</div>
</div>
</div>
</div>
</div>

What is the best strategy for testing D3/HighCharts/SVG?

Our server generates the data and then the client generates charts using HighCharts which is SVG. We are struggling to write an automated test in order to verify that the generated chart is correct.
This is what the SVG HighCharts generates
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="347" height="450"><desc>Created with Highcharts 3.0.2</desc><defs><clipPath id="highcharts-1"><rect fill="none" x="0" y="0" width="272" height="275"></rect></clipPath></defs><rect rx="5" ry="5" fill="#FFFFFF" x="0" y="0" width="347" height="450"></rect><g class="highcharts-button" style="cursor:default;" title="Chart context menu" stroke-linecap="round" transform="translate(313,10)"><title>Chart context menu</title><rect rx="2" ry="2" fill="white" x="0.5" y="0.5" width="24" height="22" stroke="none" stroke-width="1"></rect><path fill="#E0E0E0" d="M 6 6.5 L 20 6.5 M 6 11.5 L 20 11.5 M 6 16.5 L 20 16.5" stroke="#666" stroke-width="3" zIndex="1"></path><text x="0" y="13" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:12px;color:black;fill:black;" zIndex="1"></text></g><g class="highcharts-grid" zIndex="1"></g><g class="highcharts-grid" zIndex="1"><path fill="none" d="M 65 211.5 L 337 211.5" stroke="#C0C0C0" stroke-width="1" zIndex="1" opacity="1"></path><path fill="none" d="M 65 106.5 L 337 106.5" stroke="#C0C0C0" stroke-width="1" zIndex="1" opacity="1"></path><path fill="none" d="M 65 315.5 L 337 315.5" stroke="#C0C0C0" stroke-width="1" zIndex="1" opacity="1"></path></g><g class="highcharts-axis" zIndex="2"><path fill="none" d="M 142.5 316 L
142.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 181.5 316 L 181.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 219.5 316 L
219.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 258.5 316 L 258.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 297.5 316 L
297.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 336.5 316 L 336.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 103.5 316 L
103.5 321" stroke="#C0D0E0" stroke-width="1" opacity="1"></path><path fill="none" d="M 65.5 316 L 65.5 321" stroke="#C0D0E0" stroke-width="1"></path><text x="201" y="373" style="font-family:Tahoma, Arial, sans-serif;font-size:9pt;color:#505050;font-weight:bold;fill:#505050;" zIndex="7" text-anchor="middle" transform="translate(0,0)" visibility="visible"><tspan x="201">Project</tspan></text><path fill="none" d="M 65 315.5 L 337 315.5" stroke="#505050" stroke-width="1" zIndex="7" visibility="visible"></path></g><g class="highcharts-axis" zIndex="2"><text x="24.9375" y="178" style="font-family:Tahoma, Arial, sans-serif;font-size:9pt;color:#505050;font-weight:bold;fill:#505050;" zIndex="7" text-anchor="middle" transform="translate(0,0) rotate(270
24.9375 178)" visibility="visible"><tspan x="24.9375">Percent Complete (%)</tspan></text></g><g class="highcharts-series-group" zIndex="3"><g class="highcharts-series highcharts-tracker highcharts-tracker highcharts-tracker highcharts-tracker" visibility="visible" zIndex="0.1" transform="translate(65,40) scale(1 1)" style="" clip-path="url(#highcharts-1)"><rect fill="#9F2727" x="3.5" y="275.5" width="31" height="0" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect><rect fill="#9F2727" x="42.5" y="275.5" width="31" height="0" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect><rect fill="#9F2727" x="81.5" y="59.5" width="31" height="216" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect><rect fill="#9F2727" x="120.5" y="144.5" width="31" height="131" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect><rect fill="#9F2727" x="159.5" y="13.5" width="31" height="262" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect><rect fill="#9F2727" x="198.5" y="236.5" width="31" height="39" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect><rect fill="#9F2727" x="237.5" y="72.5" width="31" height="203" stroke="#FFFFFF" stroke-width="1" rx="0" ry="0"></rect></g><g class="highcharts-markers" visibility="visible" zIndex="0.1" transform="translate(65,40) scale(1 1)"></g></g><g class="highcharts-data-labels highcharts-tracker highcharts-tracker highcharts-tracker highcharts-tracker" visibility="visible" zIndex="6" transform="translate(65,40) scale(1 1)" style=""><g zIndex="1" style="cursor:default;" transform="translate(16,256)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"></text></g><g zIndex="1" style="cursor:default;" transform="translate(55,256)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"></text></g><g zIndex="1" style="cursor:default;" transform="translate(82,40)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"><tspan x="3">41%</tspan></text></g><g zIndex="1" style="cursor:default;" transform="translate(121,125)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"><tspan x="3">25%</tspan></text></g><g zIndex="1" style="cursor:default;" transform="translate(160,-6)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"><tspan x="3">50%</tspan></text></g><g zIndex="1" style="cursor:default;" transform="translate(202,217)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"><tspan x="3">8%</tspan></text></g><g zIndex="1" style="cursor:default;" transform="translate(238,53)" visibility="inherit"><text x="3" y="15" style="font-family:"HelveticaNeue-Roman", "HelveticaNeue", "Helvetica Neue", "Helvetica", "Arial", sans-serif;font-size:11px;color:#000000;line-height:14px;fill:#000000;" zIndex="1"><tspan x="3">39%</tspan></text></g></g><g class="highcharts-legend" zIndex="7" transform="translate(94,404)"><rect rx="5" ry="5" fill="#FFFFFF" x="0" y="0" width="158" height="31" visibility="visible"></rect><g zIndex="1"><g><g class="highcharts-legend-item" zIndex="1" transform="translate(8,3)"><text x="21" y="15" style="font-family:Tahoma, Arial, sans-serif;font-size:9pt;cursor:pointer;color:#274b6d;fill:#274b6d;" text-anchor="start" zIndex="2"><tspan x="21">Percent Complete-Sum</tspan></text><rect rx="2" ry="2" fill="#9F2727" x="0" y="4" width="16" height="12" zIndex="3"></rect></g></g></g></g><g class="highcharts-axis-labels" zIndex="7"></g><g class="highcharts-axis-labels" zIndex="7"><text x="57" y="322.3421875" style="font-family:Tahoma, Arial, sans-serif;font-size:8pt;width:116px;color:#666;cursor:default;line-height:14px;fill:#666;" text-anchor="end" opacity="1"><tspan x="57">0</tspan></text><text x="57" y="217.19933035714288" style="font-family:Tahoma, Arial, sans-serif;font-size:8pt;width:116px;color:#666;cursor:default;line-height:14px;fill:#666;" text-anchor="end" opacity="1"><tspan x="57">20%</tspan></text><text x="57" y="112.05647321428572" style="font-family:Tahoma, Arial, sans-serif;font-size:8pt;width:116px;color:#666;cursor:default;line-height:14px;fill:#666;" text-anchor="end" opacity="1"><tspan x="57">40%</tspan></text></g><g class="highcharts-tooltip" zIndex="8" style="cursor:default;padding:0;white-space:nowrap;" visibility="hidden" transform="translate(46,45)" opacity="0"><rect rx="3" ry="3" fill="none" x="0.5" y="0.5" width="182" height="31" fill-opacity="0.85" isShadow="true" stroke="black" stroke-opacity="0.049999999999999996" stroke-width="5" transform="translate(1, 1)"></rect><rect rx="3" ry="3" fill="none" x="0.5" y="0.5" width="182" height="31" fill-opacity="0.85" isShadow="true" stroke="black" stroke-opacity="0.09999999999999999" stroke-width="3" transform="translate(1, 1)"></rect><rect rx="3" ry="3" fill="none" x="0.5" y="0.5" width="182" height="31" fill-opacity="0.85" isShadow="true" stroke="black" stroke-opacity="0.15" stroke-width="1" transform="translate(1, 1)"></rect><rect rx="3" ry="3" fill="rgb(255,255,255)" x="0.5" y="0.5" width="182" height="31" fill-opacity="0.85" stroke="#9F2727" stroke-width="1" anchorX="194.5" anchorY="8"></rect></g></svg>
Our current strategy is to generate the SVG baselines in all browsers, save them, rerun the SVG generation using selenium driver and compare the two XML response naively.
However we noticed that the DPI and the browser heavily affects height and width of the svg, which makes the tests brittle. We also tried taking screenshots of the two charts and comparing however it was very resolution dependent.
Currently we complement the UI tests with unit tests that makes sures the input to highcharts is correct, but we want to make sure we cover all the bases.
Please help us determine the correct strategy to test SVG elements generated by libraries like highcharts and d3.js.
Thank you very much.
I think you're on the right path, using Selenium to verify the dimensions of the various elements of the chart. The key is to verify their relative dimensions compared to the <svg>'s size, maybe allowing a small margin of error, and not their absolute ones.