Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

So I need to include some pie charts in my document. As I'm using Metapost for all graphics I tried using the PiechartMP Metapost package. But for some strange reason no text shows up, just a very tiny square.

The minimal example:

\startMPinitializations
input piechartmp ;
\stopMPinitializations

\startreusableMPgraphic{pie}
u := 5mm;
r := 3u;
SetupPercent(this, "x") ;

Segment(32.5,"first",auto);
Segment(12.8,"second",auto);
Segment(22.4,"third",auto);
Segment(18.2,"fourth",auto);

beginfig(1);
PieChart(r, 0, 0, 0, 0);
SetupValue("{\tfd ", "}");
label (btex textext(Text) etex,origin);
endfig;
\stopreusableMPgraphic

\starttext
\reuseMPgraphic{pie}
\stoptext

I've tried with TEX (loading the Metapost TEX module), with \sometxt and textext commands without success. Setting a bigger or different font in Metapost just makes that square bigger, but it shows no text. Am I doing something wrong? Thanks in advance for your help.

share|improve this question
    
I looked into it but do not have a solution. PiechartMP assumes that you will be using latex or tex to typeset the logos. The obvious solution was to replace _makeText to textext in piechartmp.mp, but that did not work. The piechartmp code is too complicated to debug. –  Aditya Jan 16 '13 at 17:48
    
Hmmm I see... So better I look for another solution for doing those piecharts, maybe tikz? –  acidrums4 Jan 16 '13 at 22:22
2  
Or look for another chart (seriously, pie charts are a very bad way of representing information stevefenton.co.uk/Content/Pie-Charts-Are-Bad –  Aditya Jan 16 '13 at 23:18

1 Answer 1

The fix (short version)

You are missing the plain compatibility mode:

\starttext
  \startMPcode
    useplainlabels ;
    input piechartmp;
    Segment(30, "first");
    Segment(70, "second");
    PieChart(1cm, 0, 0, 0, 0);
    Label.auto(0)(name)(outwards,0);
    ResetSegments;
  \stopMPcode
\stoptext

screenshot1

Reason for the failure

In contrast to traditional MetaPost, MkIV uses mplib, the MetaPost library built into LuaTeX. In mplib many MetaPost variables have been placed into a namespace to separate the internal code and reduce the chance of name clashes. Usually this is no problem, users rarely alter them directly. A few MetaPost modules however, among those the PiechartMP module, rely on the original names and are thus incompatible with LuaTeX. Newer modules should use the MetaPost installlabel macro to define label directions in a portable way.

The key problem here is that PiechartMP defines the custom label direction auto using the traditional names and mplib then attempts to typeset those labels using the offsets the function thelabel calculates, which assumes the namespaced new names.

To make PiechartMP modules work with mplib you need the plain compatibility mode. This mode is included in ConTeXt since 2013.08.25 14:06. To switch to compatibility mode, use the macro useplainlabels or the corresponding environment version:

startplaincompatibility ;
  … some MetaPost code …
stoplaincompatibility ;

Workaround for older ConTeXt versions

Since the plain compatibility mode has been included rather recently and you cannot update your installation for some reason you might need a workaround. The simplest one would be to overwrite the label printing function to use the traditional names that PiechartMP uses. The drawbacks are that you can expect manually typeset labels to break.

\startMPinclusions
    input piechartmp;

    vardef thelabel@#(expr p,z) =
        if string p :
          thelabel@#(rawtextext("\definedfont[" & defaultfont & "]" & p)
            scaled defaultscale,z)
        else :
          p shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
    enddef;
\stopMPinclusions

\starttext
  \startMPcode
    Segment(30, "first");
    Segment(70, "second");
    PieChart(1cm, 0, 0, 0, 0);
    Label.auto(0)(name)(outwards,0);
    ResetSegments;
  \stopMPcode
\stoptext

Improve label typesetting

You attempted to adjust the fonts within the pie chart. Such adjustments are best done in the MetaPost instance, which should be created for those graphs. The advantage is that the code is separated and does not interfere with other MetaPost code. Additionally, the MetaPost instance can be customized using \defineMPinstance

Another improvement is to couple the MetaPost labels with ConTeXt and make them adapt to the body font. By default MetaPost draws the labels using the defaultfont. This is done by hooking the macro textext into the routing that prints the labels:

vardef _makeText primary s =
  textext(s)
enddef;

Here an example:

\defineMPinstance
  [piechartmp] [metafun]
  [textstyle=bigbodyfont]

\setupbodyfont [pagella]

\startMPinclusions{piechartmp}
  useplainlabels;
  input piechartmp;

  vardef _makeText primary s =
    textext(s)
  enddef;
\stopMPinclusions

\starttext

  \startMPcode{piechartmp}
    SetupPercent(this, "\%");

    Segment(38, "first",  auto);
    Segment(22, "second", auto);
    Segment(22, "third" , auto);
    Segment(18, "fourth", auto);

    PieChart(3cm, 1, 0, 0, .05);
    Label.auto(0)(percent)(inwards,(1,1)) withcolor white;
    Label.auto(0)(name)(outwards,0);
    ResetSegments;
  \stopMPcode

\stoptext

screenshot2

The labels are printed in a larger font because bigbodyfont is used for this instance, and they are printed in TeXGyre Pagella and adapt to the body font.

And I replaced MPinitializations with MPinclusions. The reason for that is that MetaPost initializations are global and not local to a particular MetaPost instance. Furthermore, MetaPost initializations are triggered at every graphic, which would execute the definitions more often than necessary.

Resetting the segments

Before or after each chart the segments need to be reset using ResetSegments. If the segments are not being reset, they interfere with the next graphic and too many segments will be drawn. This can be done manually, which is repetitive and error prone, so it's better to automate it. As mentioned in the previous section we figured that MetaPost initializations are being triggered at every graphic. That's exactly what we want here. So let's automatically reset the segments:

\startMPinitializations
  ResetSegments;
\stopMPinitializations

Three dimensional graphs

By default PiechartMP uses a uniform colour for three dimensional charts. MetaFun supports shading using the linear_shade macro. Fortunately PiechartMP supports this and can draw more realistic charts when MetaFun is available. Unfortunately PiechartMP checks for the existence of the old MkII variable context_spec from the special extensions code which is not included in a recent MkIV, thence it fails. The correct way is to check for metafunversion. Consider this to be a bug in PiechartMP. To fix this, either define context_spec before loading piechartmp.mp or set pc_Metafun to true, which works at any point. Here are two three dimensional graphs, one with the default rendering and one with MetaPost's linear shading.

\setupbodyfont [pagella, 16pt]

\startuseMPgraphic{pie-default}
  input piechartmp;
  Segment(28); Segment(28);
  Segment(32); Segment(12);
  PieChart(3cm, 1, 65, 0, .0);
  ResetSegments;
\stopuseMPgraphic

\startuseMPgraphic{pie-metafun}
  pc_Metafun := true;
  \includeMPgraphic{pie-default}
\stopuseMPgraphic

\starttext

  \startcombination
    \startcontent \useMPgraphic{pie-default} \stopcontent
    \startcaption Default shading            \stopcaption
    \startcontent \useMPgraphic{pie-metafun} \stopcontent
    \startcaption MetaFun shading            \stopcaption
  \stopcombination
\stoptext

screenshot

Additional notes

beginfig(1); … endfig;

Don't use beginfig(1) … endfig within an MPgraphic. The figure is already defined with \startuseMPgraphic or \startreusableMPgraphic.

SetupValue("{\tfd ", "}");

Set up the text using the textstyle key of the MetaPost instance or redefine defaultfont if you don't want to use a dedicated instance:

defaultfont := "Sans sa 1.2";

label (btex textext(Text) etex,origin);

Don't place textext(…) between btex…etex. Pick one of

draw textext("Foo");  %% draws using the body font
label("Foo", origin); %% draws using defaultfont

Example

Now let's put this all together and create a full example with all the mentioned features.

\defineMPinstance
  [piechartmp] [metafun]
  [textstyle=bigbodyfont]

\setupbodyfont [pagella]

\startMPinclusions{piechartmp}
  useplainlabels;
  input piechartmp;
  pc_Metafun := true;

  vardef _makeText primary s =
    textext(s)
  enddef;

  SetupPercent(this, "\%");
\stopMPinclusions

\startMPinitializations
  ResetSegments;
\stopMPinitializations

\startuseMPgraphic{piechartmp::pie-segments}
  Segment(28, "first"); Segment(28, "second");
  Segment(32, "third"); Segment(12, "fourth");
\stopuseMPgraphic

\startuseMPgraphic{piechartmp::pie-one}
  \includeMPgraphic{piechartmp::pie-segments}
  PieChart(3cm, 1, 70, 0, 0);
\stopuseMPgraphic

\startuseMPgraphic{piechartmp::pie-two}
  \includeMPgraphic{piechartmp::pie-segments}
  PieChart(3cm, 1, 50, 0, .2);
  Label.auto(0)(percent)(inwards,(1,1)) withcolor white;
\stopuseMPgraphic

\startuseMPgraphic{piechartmp::pie-three}
  \includeMPgraphic{piechartmp::pie-segments}
  PieChart(3cm, 1, 0, 0, .1);
  Label.auto(0)(percent)(inwards,(0,1)) withcolor white;
  Label.auto(0)(name)(outwards,0);
\stopuseMPgraphic

\startuseMPgraphic{piechartmp::pie-four}
  \includeMPgraphic{piechartmp::pie-segments}
  PieChart(3cm, 1, 60, 0, .2);
\stopuseMPgraphic

\starttext
  \startcombination
    {\useMPgraphic{piechartmp::pie-one}}   {\useMPgraphic{piechartmp::pie-two}}
    {\useMPgraphic{piechartmp::pie-three}} {\useMPgraphic{piechartmp::pie-four}}
  \stopcombination
\stoptext

screenshot4

Final thoughts

Please consider that pie charts are a really bad way of representing data visually and you should avoid them if possible, particularly the three dimensional ones. I'll just provide some links here.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.