diff --git a/uhepp-js/src/components/Graph.jsx b/uhepp-js/src/components/Graph.jsx
index 98c058e2ae86120d0cd6812dc1185df57ed43a6d..758a1be0c957fdbeca6645c0fe7fce39829575f1 100644
--- a/uhepp-js/src/components/Graph.jsx
+++ b/uhepp-js/src/components/Graph.jsx
@@ -29,6 +29,119 @@ const getMaxBin =(uhepp) => {
   return max;
 }
 
+const Badge = ({brand, label, subtext}) => (
+  <>
+   <text y={0} x={0}>
+     { brand &&
+       <tspan className="uhepp-brand">{brand}</tspan>
+     }
+     { label && 
+       <tspan dx={3} className="uhepp-label">{label}</tspan>
+     }
+   </text>
+   { subtext && subtext.split("\n").map((s, i) => 
+      <MixedText key={i} x={0} y={(i+1) * 16}>{s}</MixedText>
+    )
+   }
+ </>
+)
+
+
+const computeEquidistent = (edges) => {
+  let width = false
+  for (let i = 0; i < edges.length - 1; i++) {
+    const this_width = edges[i + 1] - edges[i]
+    if (width === false || this_width == width) {
+      width = this_width
+    } else {
+      return false
+    }
+  }
+  return width
+}
+
+const Bar = ({
+  xScale,
+  yScale,
+  leftEdge,
+  rightEdge,
+  bottom,
+  y,
+  id,
+  style={},
+  defaultColorsCycle,
+  highlighted=false,
+  onMouseOver=()=>null,
+  onMouseOut=()=>null,
+}) => (
+  <rect x={xScale(leftEdge)}
+        width={xScale(rightEdge) - xScale(leftEdge)}
+        y={yScale(bottom + y)}
+        height={yScale(bottom) - yScale(bottom + y)}
+        fill={style.color || defaultColorsCycle.get(id)}
+        opacity={highlighted ? 0.5 : 1.0}
+        onMouseOver={() => onMouseOver()}
+        onMouseOut={() => onMouseOut()} />
+)
+
+const Point = ({
+  xScale,
+  yScale,
+  x,
+  y,
+  xErr=0,
+  yErr=0,
+  style={},
+  highlighted=false,
+  onMouseOver=()=>null,
+  onMouseOut=()=>null,
+}) => (
+  <g onMouseOver={() => onMouseOver()}
+     onMouseOut={() => onMouseOut()}>
+    <circle cx={xScale(x)}
+            cy={yScale(y)}
+            fill={style.color || "#000"}
+            opacity={highlighted ? 0.8 : 1.0}
+            r="3" />
+    <line y1={yScale(y)}
+          y2={yScale(y)}
+          stroke={style.color || "#000"}
+          strokeWidth="2"
+          strokeOpacity={highlighted ? 0.8 : 1.0}
+          x1={xScale(x - xErr)}
+          x2={xScale(x + xErr)} />
+    <line y1={yScale(y + yErr)}
+          y2={yScale(y - yErr)}
+          strokeWidth="2"
+          stroke={style.color || "#000"}
+          strokeOpacity={highlighted ? 0.8 : 1.0}
+          x1={xScale(x)}
+          x2={xScale(x)} />
+  </g>
+)
+
+
+class ColorCycle {
+  constructor(colors) {
+    this.colors = colors
+    this.index = 0
+    this.cache = {}
+  }
+
+  length() {
+    return this.colors.length
+  }
+
+  get(id) {
+    if (!this.cache.hasOwnProperty(id)) {
+      const item = this.colors[this.index]
+      this.index = (this.index + 1) % this.colors.length
+      this.cache[id] = item
+    }
+    return this.cache[id]
+  }
+}
+
 // Child iterates over stacksitems = a list of rects
 // rects given freedom to highlight single bins or whole processes
 const Histogram = ({
@@ -36,6 +149,7 @@ const Histogram = ({
   yScale,
   xScale,
   colorScale,
+  defaultColorsCycle,
   highlightedBin,
   onMouseOverBin,
   children
@@ -51,55 +165,38 @@ const Histogram = ({
       stack.content.forEach((stack_item, si_i) => {
         const y_value = sumBase(uhepp.yields, stack_item["yield"], bin_i)
         if (stack.type == "stepfilled") {
-          objects.push(<rect
-            key={`rect-${stack_index}-${si_i}-${bin_i}`}
-            x={xScale(edges[bin_i-1])}
-            width={xScale(edges[bin_i + 1]) - xScale(edges[bin_i])}
-            y={yScale(bottom + y_value)}
-            height={yScale(bottom) - yScale(bottom + y_value)}
-            fill={stack_item.style ? stack_item.style.color : '#1f77b4'}
-            opacity={highlightedBin == bin_i ? 0.5 : 1.0}
-            onMouseOver={() => onMouseOverBin(bin_i)}
-            />)
-        } else if (stack.type == "points") {
           const width = xScale(edges[bin_i]) - xScale(edges[bin_i - 1])
-          const stat = sumStat(uhepp.yields, stack_item["yield"], bin_i)
+          objects.push(<Bar leftEdge={edges[bin_i - 1]}
+                            rightEdge={edges[bin_i]}
+                            bottom={bottom}
+                            y={y_value}
+                            xScale={xScale}
+                            yScale={yScale}
+                            style={stack_item.style}
+                            highlighted={highlightedBin == bin_i}
+                            defaultColorsCycle={defaultColorsCycle}
+                            id={`${stack_index}-${si_i}`}
+                            key={`key-${stack_index}-${si_i}-${bin_i}`}
+                            onMouseOver={() => onMouseOverBin(bin_i)}
+                            onMouseOverBin={() => onMouseOverBin(null)} />)
 
-          const stat_up = yScale(y_value + stat) - yScale(y_value)
-          const stat_down = yScale(y_value) - yScale(y_value - stat)
-          const gx = (xScale(edges[bin_i - 1]) + xScale(edges[bin_i])) / 2
-          const gy = yScale(bottom + y_value)
+        } else if (stack.type == "points") {
+          const stat = sumStat(uhepp.yields, stack_item["yield"], bin_i)
+          const bin_center = (edges[bin_i - 1] + edges[bin_i]) / 2
+          const width = edges[bin_i] - edges[bin_i - 1]
 
           if (stat && y_value) {
-            objects.push(<g transform={`translate(${gx}, ${gy})`}
-              key={`p-${stack_index}-${si_i}-${bin_i}`}
-              >
-              <circle
-                cx="0"
-                cy="0"
-                fill="#000"
-                opacity={highlightedBin == bin_i ? 0.8 : 1.0}
-                onMouseOver={() => onMouseOverBin(bin_i)}
-                r="3"/>
-              <line
-                y1="0"
-                y2="0"
-                stroke="#000"
-                strokeWidth="2"
-                strokeOpacity={highlightedBin == bin_i ? 0.8 : 1.0}
-                onMouseOver={() => onMouseOverBin(bin_i)}
-                x1={-width / 2}
-                x2={+width / 2} />
-              <line
-                y1={-stat_down}
-                y2={stat_up}
-                strokeWidth="2"
-                stroke="#000"
-                strokeOpacity={highlightedBin == bin_i ? 0.8 : 1.0}
-                onMouseOver={() => onMouseOverBin(bin_i)}
-                x1="0"
-                x2="0" />
-              </g>)
+            objects.push(<Point x={bin_center}
+                                y={bottom + y_value}
+                                xErr={width / 2}
+                                yErr={stat}
+                                xScale={xScale}
+                                yScale={yScale}
+                                key={`key-${stack_index}-${si_i}-${bin_i}`}
+                                highlighted={highlightedBin == bin_i}
+                                onMouseOver={() => onMouseOverBin(bin_i)}
+                                style={stack_item.style} />)
+                                
           }
         }
         if (y_value > 0) {
@@ -165,7 +262,7 @@ const length_metrix = (str) => {
   return str.length + 0.2 * long_count - 0.5 * short_count
 }
 
-const EmbeddedMathJax = ({src, posX, posY, props}) => {
+const EmbeddedMathJax = ({src, posX, posY, align="left"}) => {
   let html = tex_html;
   let node = document.createElement("div");
   const math = src.trim();
@@ -179,19 +276,96 @@ const EmbeddedMathJax = ({src, posX, posY, props}) => {
 	node.innerHTML = outerHTML;
 	let rendered_svg = node.getElementsByTagName("svg")[0];
 	const scale = 6
+	const width = rendered_svg.width.baseVal.value * scale
 	const transX = rendered_svg.width.baseVal.value * scale / rendered_svg.viewBox.baseVal.width
 	const transY = rendered_svg.height.baseVal.value * scale / rendered_svg.viewBox.baseVal.height
+  let alignTransX = 0
+  if (align == "center") {
+    alignTransX = -width / 2
+  } else if (align == "right") {
+    alignTransX = -width
+  }
+
   return <g 
-            transform={`matrix(${transX} 0 0 ${transY} ${posX} ${posY})`}
-					  dangerouslySetInnerHTML={{__html: rendered_svg.innerHTML}} { ...props}></g>
+            transform={`matrix(${transX} 0 0 ${transY} ${posX + alignTransX} ${posY})`}
+					  dangerouslySetInnerHTML={{__html: rendered_svg.innerHTML}}></g>
 }
 
-const MixedText = ({children, x=0, y=0}) => {
+const MixedText = ({children, x=0, y=0, align="left"}) => {
+  if (children.join) {
+    children = children.join("")
+  }
   const embedded = `\\textsf{${children}}`
   const switched = embedded.replaceAll(/\$([^$]*)\$/g, "}$1\\textsf{")
   const cleared = switched.replaceAll("\\textsf{}", "")
 
-  return <EmbeddedMathJax posX={x} posY={y} src={cleared} />
+  return <EmbeddedMathJax posX={x} posY={y} src={cleared} align={align} />
+}
+
+const Legend = ({
+  post_uhepp,
+  setShowTotal,
+  defaultColorsCycle,
+  showTotal,
+  highlightedBin
+}) => {
+  const lineSkip = 16;
+  const mathSkip = 120;
+  let i = 0
+  let legend = []
+  post_uhepp.stacks.map((stack, stack_index) => {
+      stack.content.map((stack_item, si_i) => {
+        if (stack.type == "points") {
+            legend.push(<Point x={10}
+                                y={(i + 1) * lineSkip - 5}
+                                xErr={10}
+                                yErr={5}
+                                xScale={(x) => x}
+                                yScale={(y) => y}
+                                key={`legend-${i}`}
+                                onMouseOver={() => setShowTotal(true)}
+                                onMouseOut={() => setShowTotal(false)}
+                                style={stack_item.style} />)
+        } else {
+          legend.push(<Bar leftEdge={0}
+                            rightEdge={20}
+                            bottom={(i + 1) * lineSkip}
+                            y={-10}
+                            xScale={(x) => x}
+                            yScale={(y) => y}
+                            style={stack_item.style}
+                            onMouseOver={() => setShowTotal(true)}
+                            onMouseOut={() => setShowTotal(false)}
+                            defaultColorsCycle={defaultColorsCycle}
+                            id={`${stack_index}-${si_i}`}
+                            key={`legend-${stack_index}-${si_i}`} />)
+        }
+        if (highlightedBin != null) {
+          const y_value = sumBase(post_uhepp.yields, stack_item["yield"], highlightedBin)
+          const stat = sumStat(post_uhepp.yields, stack_item["yield"], highlightedBin)
+
+          const label = y_value.toFixed(1) + " ± " + stat.toFixed(1)
+          legend.push(<text fontSize={12} textAnchor="end" x={mathSkip} y={(i + 1) * lineSkip}
+                key={`legend-text-${i}`}>{label}</text>)
+        } else if (showTotal) {
+          const y_value = sumBase(post_uhepp.yields, stack_item["yield"])
+          const stat = sumStat(post_uhepp.yields, stack_item["yield"])
+
+          const label = y_value.toFixed(1) + " ± " + stat.toFixed(1)
+          legend.push(<text fontSize={12} textAnchor="end" x={mathSkip} y={(i + 1) * lineSkip}
+                key={`legend-text-${i}`}>{label}</text>)
+
+        } else {
+          const label = stack_item.label
+          legend.push(
+            <MixedText x={30} y={(i + 1) * lineSkip}
+                  key={`legend-text-${i}`}>{label}</MixedText>)
+        }
+        i++;
+      })
+  })
+
+  return legend
 }
 
 const UheppHist = ({width, height, uhepp}) => {
@@ -199,6 +373,20 @@ const UheppHist = ({width, height, uhepp}) => {
   const [highlightedBin, setHighlightedBin] = useState(null);
   const [showTotal, setShowTotal] = useState(false);
 
+  const defaultColorsCycle = new ColorCycle([
+    "#1f77b4",
+    "#ff7f0e",
+    "#2ca02c",
+    "#d62728",
+    "#9467bd",
+    "#8c564b",
+    "#e377c2",
+    "#7f7f7f",
+    "#bcbd22",
+    "#17becf",
+    "#1f77b4",
+  ])
+
   const post_uhepp = Object.assign({}, uhepp, {
       yields: preprocessData({
         yields: uhepp.yields,
@@ -214,10 +402,18 @@ const UheppHist = ({width, height, uhepp}) => {
 		bottom: 60,
 		left: 80,
 		right: 80,
+    sep: 3,
 	}
 
 	const xMax = width - margin.left - margin.right
-	const yMax = height - margin.top - margin.bottom
+	let yMax = height - margin.top - margin.bottom 
+  let ratioMax = 0 
+  const hasRatio = (uhepp.ratio && uhepp.ratio.length)
+  if (hasRatio) {
+    const ratioFraction = (uhepp.layout && uhepp.layout.ratio_fraction) || 0.25
+	  yMax = (height - margin.top - margin.bottom - margin.sep) * (1 - ratioFraction)
+	  ratioMax = (height - margin.top - margin.bottom - margin.sep) * (ratioFraction)
+  }
 
 	const xScale = scaleLinear({
 		range: [0, xMax],
@@ -225,81 +421,19 @@ const UheppHist = ({width, height, uhepp}) => {
 	})
 	const yScale = scaleLinear({
 		range: [yMax, 0],
-		domain: [0, getMaxBin(post_uhepp) * 1.3],
+		domain: [0, getMaxBin(post_uhepp) * 1.5],
+	})
+	const ratioScale = scaleLinear({
+		range: [ratioMax, 0],
+		domain: [
+      (uhepp.ratio_axis && uhepp.ratio_axis.min) || 0.5,
+      (uhepp.ratio_axis && uhepp.ratio_axis.max) || 1.5,
+    ],
 	})
 
 
-  let i = 0
-  let legend = []
-  post_uhepp.stacks.reverse().map(stack => {
-      stack.content.reverse().map(stack_item => {
-        if (stack.type == "points") {
-            let color = stack_item.style ? stack_item.style.color : '#000'
-            legend.push(<g key={`legend-${i}`}
-                onMouseOver={() => setShowTotal(true)}
-                onMouseOut={() => setShowTotal(false)}
-                >
-              <circle
-                cx={width * 0.5 + 10}
-                cy={25 + i * 20}
-                stroke={color}
-                r="3"/>
-              <line
-                y1={25 + i * 20}
-                y2={25 + i * 20}
-                stroke={color}
-                strokeWidth="2"
-                onMouseOver={() => setShowTotal(true)}
-                onMouseOut={() => setShowTotal(false)}
-                x1={width * 0.5}
-                x2={width * 0.5 + 20} />
-              <line
-                y1={20 + i * 20}
-                y2={30 + i * 20}
-                strokeWidth="2"
-                stroke={color}
-                onMouseOver={() => setShowTotal(true)}
-                onMouseOut={() => setShowTotal(false)}
-                x1={width * 0.5}
-                x1={width * 0.5 + 10}
-                x2={width * 0.5 + 10} />
-              </g>)
-        } else {
-          legend.push(
-            <rect x={width * 0.5} y={20 + i * 20}
-                  key={`legend-${i}`}
-                  onMouseOver={() => setShowTotal(true)}
-                  onMouseOut={() => setShowTotal(false)}
-                  height={10} width={20}
-                  fill={stack_item.style ? stack_item.style.color : '#1f77b4'}
-                  />)
-        }
-        if (highlightedBin != null) {
-          const y_value = sumBase(post_uhepp.yields, stack_item["yield"], highlightedBin)
-          const stat = sumStat(post_uhepp.yields, stack_item["yield"], highlightedBin)
-
-          const label = y_value.toFixed(1) + " ± " + stat.toFixed(1)
-          legend.push(<text fontSize={12} textAnchor="end" x={width * 0.5 + 100} y={30 + i * 20}
-                key={`legend-text-${i}`}>{label}</text>)
-        } else if (showTotal) {
-          const y_value = sumBase(post_uhepp.yields, stack_item["yield"])
-          const stat = sumStat(post_uhepp.yields, stack_item["yield"])
-
-          const label = y_value.toFixed(1) + " ± " + stat.toFixed(1)
-          legend.push(<text fontSize={12} textAnchor="end" x={width * 0.5 + 100} y={30 + i * 20}
-                key={`legend-text-${i}`}>{label}</text>)
 
-        } else {
-          const label = stack_item.label
-          legend.push(
-            <MixedText x={width * 0.5 + 30} y={30 + i * 20}
-                  key={`legend-text-${i}`}>{label}</MixedText>)
-        }
-        i++;
-      })
-      stack.content.reverse()
-  })
-  post_uhepp.stacks.reverse()
+  const equidistent = computeEquidistent(uhepp.bins.rebin || uhepp.bins.edges)
 
 	return (
   <div style={{width: '100%', margin: '0 auto'}}>
@@ -316,30 +450,36 @@ const UheppHist = ({width, height, uhepp}) => {
 				</pattern>
 
 				<Group top={margin.top} left={margin.left}>
-
-         <text y={30} x={13} className="uhepp-brand">ATLAS</text>
-         <text y={30} x={75} className="uhepp-label">Internal</text>
-
          <Histogram
             uhepp={post_uhepp}
             highlightedBin={highlightedBin}
             onMouseOverBin={binIndex => setHighlightedBin(binIndex)}
             stack_index={0}
+            defaultColorsCycle={defaultColorsCycle}
             xScale={xScale}
             yScale={yScale}
           />
 
-        {legend}
-  
+        <Group top={26} left={13}>
+          <Badge brand={uhepp.badge.brand} label={uhepp.badge.label} subtext={uhepp.badge.subtext} />
+        </Group>
+
+        <Group top={5} left={xMax * 0.65}>
+          <Legend post_uhepp={post_uhepp}
+                  setShowTotal={setShowTotal}
+                  showTotal={showTotal}
+                  defaultColorsCycle={defaultColorsCycle}
+                  highlightedBin={highlightedBin} />
+        </Group>
+
 		 		<AxisBottom
 						scale={xScale}
 						top={yMax}
 						stroke={'#1b1a1e'}
 						tickTextFill={'#1b1a1e'}
 						tickTransform="translate(0, -8)"
+					  tickComponent={hasRatio ? (props) => <></> : undefined}
 					/>
-        <MixedText y={yMax * 1.08} x={xMax * 0.9}>{uhepp.variable.symbol}</MixedText>
-
 		 		<AxisBottom
 						scale={xScale}
 						top={yMax}
@@ -349,16 +489,30 @@ const UheppHist = ({width, height, uhepp}) => {
 						tickTransform="translate(0, -4)"
 					  tickComponent={(props) => <></>}
 					/>
-					<AxisLeft
+        { !hasRatio && 
+          <MixedText y={yMax + 30} x={xMax - 10} align="right">
+            {uhepp.variable.name ? uhepp.variable.name + ' ' : ''}
+            {uhepp.variable.symbol}
+            {uhepp.variable.unit ? ' / ' + uhepp.variable.unit : ''}
+          </MixedText>
+        }
+
+				<AxisLeft
 						scale={yScale}
 						top={0}
 						left={0}
-						label={'Events'}
 						stroke={'#1b1a1e'}
 						tickTextFill={'#1b1a1e'}
 						tickTransform="translate(8, 0)"
 					/>
-					<AxisLeft
+        <g transform={`matrix(0 -1 1 0 ${-margin.left + 20} 10)`}>
+          <MixedText y={0} x={0} align="right">
+            Events
+            { equidistent ? ' / ' + equidistent + (uhepp.variable.unit ? " " + uhepp.variable.unit : '') : ''}
+          </MixedText>
+        </g>
+
+				<AxisLeft
 						scale={yScale}
 						top={0}
 						left={0}
@@ -368,7 +522,7 @@ const UheppHist = ({width, height, uhepp}) => {
             tickLength={4}
 					  tickComponent={(props) => <></>}
 					/>
-					<AxisRight
+				<AxisRight
 						scale={yScale}
 						top={0}
 						left={xMax}
@@ -376,7 +530,7 @@ const UheppHist = ({width, height, uhepp}) => {
 					  tickComponent={(props) => <></>}
 						tickTransform="translate(-8, 0)"
 					/>
-					<AxisRight
+				<AxisRight
 						scale={yScale}
 						top={0}
 						left={xMax}
@@ -403,6 +557,93 @@ const UheppHist = ({width, height, uhepp}) => {
 						tickTransform="translate(0, 4)"
 					/>
 				</Group>
+
+		<Group top={margin.top + margin.sep + yMax} left={margin.left}>
+		 		<AxisBottom
+						scale={xScale}
+						top={ratioMax}
+						stroke={'#1b1a1e'}
+						tickTextFill={'#1b1a1e'}
+						tickTransform="translate(0, -8)"
+					/>
+		 		<AxisBottom
+						scale={xScale}
+						top={ratioMax}
+            numTicks={50}
+						stroke={'#1b1a1e'}
+            tickLength={4}
+						tickTransform="translate(0, -4)"
+					  tickComponent={(props) => <></>}
+					/>
+        <MixedText y={ratioMax + 30} x={xMax - 10} align="right">
+          {uhepp.variable.name ? uhepp.variable.name + ' ' : ''}
+          {uhepp.variable.symbol}
+          {uhepp.variable.unit ? ' / ' + uhepp.variable.unit : ''}
+        </MixedText>
+
+				<AxisLeft
+						scale={ratioScale}
+						top={0}
+						left={0}
+						stroke={'#1b1a1e'}
+						tickTextFill={'#1b1a1e'}
+            numTicks={5}
+						tickTransform="translate(8, 0)"
+					/>
+        { uhepp.ratio_axis.label && 
+          <g transform={`matrix(0 -1 1 0 ${-margin.left + 20} ${ratioMax / 2})`}>
+            <MixedText y={0} x={0} align="center">
+              { uhepp.ratio_axis.label }
+            </MixedText>
+          </g>
+        }
+
+				<AxisLeft
+						scale={ratioScale}
+						top={0}
+						left={0}
+						stroke={'#1b1a1e'}
+            numTicks={20}
+						tickTransform="translate(4, 0)"
+            tickLength={4}
+					  tickComponent={(props) => <></>}
+					/>
+				<AxisRight
+						scale={ratioScale}
+						top={0}
+						left={xMax}
+            numTicks={5}
+						stroke={'#1b1a1e'}
+					  tickComponent={(props) => <></>}
+						tickTransform="translate(-8, 0)"
+					/>
+				<AxisRight
+						scale={ratioScale}
+						top={0}
+						left={xMax}
+						stroke={'#1b1a1e'}
+            numTicks={20}
+					  tickComponent={(props) => <></>}
+            tickLength={4}
+						tickTransform="translate(-4, 0)"
+					/>
+					<AxisTop
+						scale={xScale}
+						top={0}
+						stroke={'#1b1a1e'}
+					  tickComponent={(props) => <></>}
+						tickTransform="translate(0, 8)"
+					/>
+					<AxisTop
+						scale={xScale}
+						top={0}
+						stroke={'#1b1a1e'}
+            numTicks={50}
+					  tickComponent={(props) => <></>}
+            tickLength={4}
+						tickTransform="translate(0, 4)"
+					/>
+        </Group>
 			</svg>
   </div>
 	)