(*:Version: Mathematica 2.0 *)

(*:Name: Graphics`Graphics` *)

(*:Title: Additional Graphics Functions *)

(*:Author: Wolfram Research, Inc. *)

(*:History:
	Original Version by Wolfram Research, Inc.
	Revised by Michael Chan and Kevin McIsaac (Wolfram Research), 
	March, 1990.  Further revisions by Bruce Sawhill (Wolfram
	Research), Sept., 1990.
	Further revisions by ECM (Wolfram Research), Dec., 1990.
	Removal of 3D graphics functions to the package Graphics3D.m and
	minor revisions by John M. Novak, March, 1991.
	More extensive revisions by John M. Novak, Nov. 1991.
		(PieChart, log plots, ScaledPlot, bar charts, etc.)
*)

(*:Summary:
     Defines some functions to extend Mathematica's graphing capabilities.
*)

(*:Keywords:
	Log, Graphics, ListPlot, Scale, Polar
*)

(*:Requirements: None *)

(*:Warnings:
	Expands the definitions of PlotStyle.
*)

(*:Sources: *)

BeginPackage["Graphics`Graphics`",
	"Utilities`FilterOptions`"];

(* Usage messages *)

LinearScale::usage =
"LinearScale[xmin, xmax] gives a list of \"nice\" values between xmin and xmax
suitable for use as tick mark positions.  LinearScale[xmin, xmax, n] attempts
to find n such values.";

LogScale::usage =
"LogScale[xmin, xmax] gives a list of \"nice\" values between xmin and xmax
suitable for use as tick mark positions on a logarithmic scale.
LogScale[xmin, xmax, n] attempts to find n such values.";

UnitScale::usage =
"UnitScale[xmin, xmax, unit] gives a list of \"nice\" values between xmin and
xmax that are multiples of unit.  UnitScale[xmin, xmax, unit, n] attempts to
find n such values.";

PiScale::usage =
"PiScale[xmin, xmax] gives a list of \"nice\" values between xmin and xmax that
are multiples of Pi.  PiScale[xmin, xmax, n] attempts to find n such values.";

LogGridMinor::usage =
"LogGridMinor[xmin, xmax] gives a list of \"nice\" values between xmin and
xmax suitable for use as grid line positions on a logarithmic scale. The
positions are the same as those for major and minor tick marks from LogScale.
LogGridMinor[xmin, xmax, n] attempts to find n such values.";

LogGridMajor::usage =
"LogGridMajor[xmin, xmax] gives a list of \"nice\" values between xmin and
xmax suitable for use as grid line positions on a logarithmic scale. The
positions are the same as those for major tick marks from LogScale.
LogGridMajor[xmin, xmax, n] attempts to find n such values.";

TextListPlot::usage =
"TextListPlot[{y1, y2, ...}] plots a list, with each point {i,yi} rendered as
its index number i.  TextListPlot[{{x1,y1},{x2,y2}, ...}] renders the point
{xi,yi} as its index number i.  TextListPlot[{{x1, y1, t1}, {x2, y2, t2}, ...}]
renders the point {xi,yi} as the text ti.";

LabeledListPlot::usage =
"LabeledListPlot[{y1, y2, ...}] plots a list, with each point {i,yi} labeled
with its index number i.  LabeledListPlot[{{x1,y1},{x2,y2}, ...}] labels the
point {xi,yi} with its index number i.  TextListPlot[{{x1, y1, t1},
{x2, y2, t2}, ...}] labels the point {xi,yi} with the text ti.";

DisplayTogether::usage =
"DisplayTogether[plotcommands, opts] takes a sequence of plot commands (e.g.,
Plot[Sin[x], {x,0, 2 Pi}], etc.) and combines them to produce a single
graphic.  The constraints on this are that the commands must all be able
to accept the option DisplayFunction->Identity as an argument, and must
all produce graphics that can be shown together by use of the Show
command. Options for the type of graphic to be produced can be passed in."

DisplayTogetherArray::usage =
"DisplayTogether[plotcommands, opts] takes a sequence of plot commands (e.g.,
Plot[Sin[x], {x,0, 2 Pi}], etc.) and combines them to produce a GraphicsArray
of the plots.  The constraint on this is that the commands must all be able
to accept the option DisplayFunction->Identity as an argument. Note that the
plotcommands can also be placed in an array, suitable for arranging the
output GraphicsArray.  Options for GraphicsArray can be passed in."

ListAndCurvePlot::usage =
"ListAndCurvePlot[list1,list2,...,curve1,curve2...,range] puts
curves in a single variable and lists of data in a single plot.
Curves are given as in Plot, lists as in ListPlot.  The range is
specified as in Plot, and is used in the same fashion.  The
function accepts standard Graphics options, plus PlotStyle
(which works as in Plot).  Lists and curves can be specified in
any order, and can be intermixed.";

LogPlot::usage =
"LogPlot[f, {x, xmin, xmax}] generates a plot of Log[f] as a function of x.";

LogListPlot::usage =
"LogListPlot[{y1, y2, ...}] or LogListPlot[{{x1, y1}, {x2, y2}, ...}] generates
a plot of Log[yi] against the xi.";

LinearLogPlot::usage =
"LinearLogPlot[f, {x, xmin, xmax}] generates a plot of Log[f] as a function
of x.";

LinearLogListPlot::usage =
"LinearLogListPlot[{y1, y2, ...}] or
LinearLogListPlot[{{x1, y1}, {x2, y2}, ...}] generates
a plot of Log[yi] against the xi.";

LogLinearPlot::usage = 
"LogLinearPlot[f, {x, xmin, xmax}] generates a plot of f as a function of
Log[x]." ;

LogLinearListPlot::usage = 
"LogLinearListPlot[{y1, y2, ...}] or
LogLinearListPlot[{{x1, y1}, {x2, y2}, ...}] generates a plot of yi against
Log[xi].";

LogLogPlot::usage = 
"LogLogPlot[f, {x, xmin, xmax}] generates a plot of Log[f] as a function of
Log[x]." ;

LogLogListPlot::usage = 
"LogLogListPlot[{y1, y2, ...}] or LogLogListPlot[{{x1, y1}, {x2, y2}, ...}]
generates a plot of Log[yi] against Log[xi].";

ScaledPlot::usage =
"ScaledPlot[f, {x, xmin, xmax}] generates a plot of the function
with each coordinate scaled by a function specified by the Scale
option."

ScaledListPlot::usage =
"ScaledListPlot[data] generates a plot with each data point scaled
by functions specified in the Scale option."

Scale::usage =
"Scale is an option for ScaledPlot and ScaledListPlot.  It
is given as a pure function or a pair of pure functions; the
first is applied to all x values, the second to all y values."

PolarPlot::usage =
"PolarPlot[r, {t, tmin, tmax}] generates a polar plot of r as a function of t.
PolarPlot[{r1, r2, ...}, {t, tmin, tmax}] plots each of the ri as a function of
t on the same graph.";

PolarListPlot::usage =
"PolarListPlot[{r1, r2, ...}] generates a polar plot, assuming that the ri are
equally spaced in angle.";

ErrorListPlot::usage =
"ErrorListPlot[{{y1, dy1}, {y2, dy2}, ...}] plots a list of data with error
bars. ErrorListPlot[{{x1, y1, dy1}, ...}] allows x, as well as y, positions to
be specified.";

BarChart::usage =
"BarChart[list1, list2, ...] generates a bar chart of the data in the lists.";

GeneralizedBarChart::usage =
"GeneralizedBarChart[{{pos1, height1, width1}, {pos2, height2, width2},...}]
generates a bar chart with the bars at the given positions, heights, and
widths.";

StackedBarChart::usage =
"StackedBarChart[list1, list2, ...] generates a stacked bar chart of the
data in the lists.";

PercentileBarChart::usage =
"PercentileBarChart[list1, list2, ...] generates a stacked bar chart with
the data scaled so that the sum of the absolute values at a given point is 1.";

(* The option BarStyle specifies the default style for the bars.  BarSpacing
gives the fraction of the bar width to be allowed as separation between the 
bars.  BarEdges specifies whether edges are to be drawn around the bars.
BarEdgeStyle gives the style for the edges. BarOrientation can be either
Horizontal or Vertical to specify the orientation of the bars. *)

BarStyle::usage =
"BarStyle is an option for the bar charts that determines the default style
for the bars.  If there is only one data set, the styles are cycled amongst
the bars; if there are multiple data sets, the styles are cycled amongst
the sets.  If it is a function, the function is applied to the heights of
each of the bars.";

BarLabels::usage =
"BarLabels is an option for BarChart, StackedBarChart, and PercentileBarChart,
that allows a label to be placed at the tick mark for each bar (or group of
bars for multiple data sets).  Labels are specified in a list.";

BarValues::usage =
"BarValues is an option for BarChart and GeneralizedBarChart that allows
the length of the bar to be displayed above each bar.  See also
BarValuePosition.";

BarEdges::usage =
"BarEdges is an option for the bar charts that determines whether edges are to be
drawn around the bars.";

BarEdgeStyle::usage =
"BarEdgeStyle is an option for the bar charts that determines the style for the
edges.";

BarSpacing::usage =
"BarSpacing is an option for BarChart that determines the fraction of the
bar width of a bar to space the bars in a group of bars; or, in 
StackedBarChart and PercentileBarChart, the space between the bars.  See
also BarGroupSpacing.";

BarGroupSpacing::usage =
"BarGroupSpacing is an option for BarChart that determines the spacing
between groups of bars (individual bars when only one data set is used).";

BarOrientation::usage =
"BarOrientation is an option for BarChart that determines whether the bars are
oriented vertically or horizontally.";

Vertical::usage = Horizontal::usage =
"Vertical and Horizontal are possible values for BarOrientation, an option of
BarChart.";

PieChart::usage =
"PieChart[{y1, y2, ...}] generates a pie chart of the values yi.
The values yi need to be positive. Several options (PieLabels,
PieStyle, PieLineStyle, PieExploded) are available to modify
the style of the pie.";

PieLabels::usage =
"PieLabels is an option for PieChart; it accepts a list of
expressions to be used as labels on the pie wedges. If None,
no labels are placed.";

PieStyle::usage =
"PieStyle is an option for PieChart; it accepts a list of
styles that are matched with the polygon for each pie wedge.
Default behavior will give each wedge a different color.";

PieLineStyle::usage =
"PieLineStyle is an option for PieChart.  It accepts a style
or list of styles that will be applied to all of the lines in
the pie chart (around the wedges).";

PieExploded::usage =
"PieExploded is an option for PieChart.  It accepts a list of
distances or pairs of a wedge number and a matching distance.
Distances are expressed as a ratio of the distance to the
radius of the pie; ie, .1 moves a wedge outward 1/10th the
radius of the pie.  Wedges are numbered counterclockwise from
theta = 0 (a line extending right from the center of the pie).";

TransformGraphics::usage =
"TransformGraphics[graphics, f] applies the function f to all lists of
coordinates in graphics.";

SkewGraphics::usage =
"SkewGraphics[graphics, m] applies the matrix m to all coordinates in graphics.";

PlotStyle::usage =
"PlotStyle is an option for Plot and ListPlot that specifies the style of lines
or points to be plotted.  PlotStyle[graphics] will return the PlotStyle for
a graphic image created by Plot or ListPlot.";

Begin["`Private`"]

(* Define a better NumberQ *)

numberQ[x_] := NumberQ[N[x]]

(* The following is a useful internal utility function to be
used when you have a list of values that need to be cycled to
some length (as PlotStyle works in assigning styles to lines
in a plot).  The list is the list of values to be cycled, the
integer is the number of elements you want in the final list. *)

CycleValues[{},_] := {}

CycleValues[list_List, n_Integer] :=
	Module[{hold = list},
		While[Length[hold] < n,hold = Join[hold,hold]];
		Take[hold,n]
	]

CycleValues[item_,n_] := CycleValues[{item},n]

(* PlotStyle *)

Unprotect[PlotStyle];

PlotStyle[Graphics[g:{{__,_List}..},opts___]] :=
  Map[PlotStyle[Graphics[#,opts]]&, g]

PlotStyle[Graphics[g_List,opts___]] := 
	Module[{q},
	 If[
	  Length[
	   q=Select[Drop[g,-1],
	             MemberQ[{RGBColor,GrayLevel,Thickness,Dashing,PointSize},
			     Head[#]]&
		   ]
		] > 1,
	   {q}, q]]

Protect[PlotStyle];

(* Linear Scale *)

LinearScale[min_, max_, n_Integer:8] :=
	Module[{spacing, t, nmin=N[min], nmax=N[max]},
		(spacing = TickSpacing[nmax-nmin, n, {1, 2, 2.5, 5, 10}] ;
		t = Range[Ceiling[nmin/spacing - 0.05] spacing, max, spacing] ;
		Map[{#, If[Round[#]==#, Round[#], #]}&, t])
	/; nmin < nmax
	]

TickSpacing[dx_, n_Integer, prefs_List] :=
	Module[ { dist=N[dx/n], scale } ,
		scale = 10.^Floor[Log[10., dist]] ;
		dist /= scale ;
		If[dist < 1, dist *= 10 ; scale /= 10] ;
		If[dist >= 10, dist /= 10 ; scale *= 10] ;
		scale * First[Select[prefs, (dist <= #)&]]
	]

(* LogScale *)

LogScale[min_, max_, n_Integer:6] :=
        Module[{pts} ,
		pts = GenGrid[ min, max, n] ;
		Join[ Map[ LogTicks, pts ], MinorLogTicks[pts]]
	] /; N[min] < N[max]

LogGridMajor[ min_, max_, n_Integer:6] :=
        Module[{pts} ,
                pts = GenGrid[ min, max, n] ; 
                Map[ Log[10, #]& , pts ]
        ] /; N[min] < N[max]

LogGridMinor[ min_, max_, n_Integer:6] :=
        Module[{pts} ,
                pts = GenGrid[ min, max, n] ; 
		Union[ Map[ Log[10., #]&,pts],
                       Map[ First, MinorLogTicks[pts]]]
        ] /; N[min] < N[max]

GenGrid[min_, max_, n_Integer:6] :=
        Module[{nmin=N[min], nmax=N[max], imin, imax, nper, t, tl} ,
                imin=Round[nmin] ;
                imax=Round[nmax] ;
                If[imin == imax, imax+=1];
                nper = Floor[n/(imax - imin)] ;
                If[nper > 0,
                        t = 10.^Range[imin, imax] ;
                        tl = Take[ $LogPreferances,
                                Min[nper, Length[$LogPreferances]] ] ;
                        t = Flatten[Outer[Times, t, tl]] ;
                        t = Sort[t] ,
                        (* else *)
                        nper = Ceiling[(imax - imin)/n] ;
                        t = 10.^Range[imin, imax, nper]
                ] ;
	t
        ]

LogTicks[x_] :=
	{Log[10., x],NumberForm[x]}

MinorLogTicks[pts_] :=
        Module[ {cd1=pts, cd2 },
                cd2 = Transpose[{ Drop[cd1, {1}],
                                     Drop[Map[ Minus, cd1], {-1}]}] ;
                cd2 = Apply[ Plus, cd2, 1] ;
                cd2 = Map[ MinorAux1, cd2] ;
                cd1 = Transpose[ { Drop[cd1, {-1}], cd2}] ;
                Flatten[ Map[ MinorAux2, cd1], 1]
        ]       

 
MinorAux2[{xst_, {del_ , n_}}] :=
        Module[{xfin = xst+del*(n-1),pts,x},
                pts = Table[x, {x, xst+del, xfin, del}] ;
                Map[ {Log[10., #], "", {0.6/160., 0.},
                                {Thickness[0.001]}}&, pts ]
        ]
 

MinorAux1[x_] :=
        Module[{n=Floor[ x/10^Floor[ Log[10., x]]]},
                If[ n < 1, {1,1}, {x/n, n}]
        ]

$LogPreferances = {1, 5, 2, 3, 1.5, 7, 4, 6, 1.2, 8, 9, 1.3, 2.5, 1.1, 1.4}
{1, 5, 2, 3, 1.5, 7, 4, 6, 1.2, 8, 9, 1.3, 2.5, 1.1, 1.4}

(* UnitScale *)

UnitScale[min_, max_, unit_, n_Integer:8] :=
	Module[{spacing, t,
		imin=Ceiling[N[min/unit]],imax = Floor[N[max/unit]]},
		(spacing = TickSpacing[imax-imin, n, {1, 2, 5, 10}] ;
		t = Range[Ceiling[imin/spacing - 0.05] spacing, imax,
				spacing] ;
		t = Union[Round[t]] ;
		Map[{N[# unit], # unit}&, t])
	/; N[min] < N[max]
	]

(* PiScale *)

PiScale[min_, max_, n_Integer:8] :=
	UnitScale[min, max, Pi/2, n] /; min < max

(* TextListPlot *)

TextListPlot[data:{_?numberQ ..}, opts___] :=
        TextListPlot[Transpose[{Range[Length[data]], 
					data, Range[Length[data]]}]]

TextListPlot[data:{{_?numberQ, _}..}, opts___] :=
        TextListPlot[Transpose[Join[Transpose[data], {Range[Length[data]]}]]]

TextListPlot[data:{{_?numberQ, _?numberQ, _}..}, opts___] :=
        Show[Graphics[ Text[Last[#], Take[#, 2]]& /@ data,
                        opts, Axes->Automatic]]

(* LabeledListPlot *)

LabeledListPlot[data:{_?numberQ ..}, opts___] :=
        LabeledListPlot[Transpose[{Range[Length[data]],
                                        data, Range[Length[data]]}]]

LabeledListPlot[data:{{_?numberQ, _}..}, opts___] :=
        LabeledListPlot[Transpose[Join[Transpose[data], {Range[Length[data]]}]]]

LabeledListPlot[data:{{_?numberQ, _?numberQ, _}..}, opts___] :=
	Show[Graphics[ {PointSize[0.015], {Point[Take[#, 2]], 
		Text[Last[#], Scaled[{0.015, 0}, Take[#, 2]], {-1, 0}]
			} } & /@ data ,
		opts, Axes->Automatic]]

(* Log Plots *)

SetAttributes[{LogPlot, LinearLogPlot, LogLinearPlot, LogLogPlot, 
	ScaledPlot}, HoldFirst];

(* adopt as default options those of ParametricPlot and ListPlot *)

Options[LogPlot] = Options[LogLinearPlot] = Options[LinearLogPlot] =
	Options[LogLogPlot] = Options[ParametricPlot];

Options[LogListPlot] = Options[LogLinearListPlot] = Options[LinearLogListPlot] =
	Options[LogLogListPlot] = Options[ListPlot];

LogPlot = LinearLogPlot; LogListPlot = LinearLogListPlot;

LinearLogPlot[fun_,range_,opts___] :=
	ScaledPlot[fun,range,
		Scale -> {#&, Log[10,#]&},
		Sequence @@ tickopts[Automatic, LogScale,
			 LinearLogPlot, {opts}],
		scaleplotrange[LinearLogPlot, {opts}],
		opts,
		Sequence @@ Options[LinearLogPlot]
	]

LogLinearPlot[fun_, range_, opts___] :=
	ScaledPlot[fun, range,
		Scale -> {Log[10, #]&, #&},
		Sequence @@ tickopts[LogScale, Automatic,
			LogLinearPlot, {opts}],
		scaleplotrange[LogLinearPlot, {opts}],
		opts,
		Sequence @@ Options[LogLinearPlot]
	]

LogLogPlot[fun_, range_, opts___] :=
	ScaledPlot[fun, range,
		Scale -> {Log[10, #]&, Log[10, #]&},
		Sequence @@ tickopts[LogScale, LogScale,
			LogLogPlot, {opts}],
		scaleplotrange[LogLogPlot, {opts}],
		opts,
		Sequence @@ Options[LogLogPlot]
	]

LinearLogListPlot[data_, opts___] :=
	ScaledListPlot[data,
		Scale -> {#&, Log[10,#]&},
		Sequence @@ tickopts[Automatic, LogScale,
			 LinearLogListPlot, {opts}],
		scaleplotrange[LinearLogListPlot, {opts}],
		opts,
		Sequence @@ Options[LinearLogListPlot]
	]

LogLinearListPlot[data_, opts___] :=
	ScaledListPlot[data,
		Scale -> {Log[10, #]&, #&},
		Sequence @@ tickopts[LogScale, Automatic,
			LogLinearListPlot, {opts}],
		scaleplotrange[LogLinearListPlot, {opts}],
		opts,
		Sequence @@ Options[LogLinearListPlot]
	]

LogLogListPlot[data_, opts___] :=
	ScaledListPlot[data,
		Scale -> {Log[10, #]&, Log[10, #]&},
		Sequence @@ tickopts[LogScale, LogScale,
			LogLogListPlot, {opts}],
		scaleplotrange[LogLogListPlot, {opts}],
		opts,
		Sequence @@ Options[LogLogListPlot]
	]

(* this is an internal auxiliary function for the Log Plots
	(and any other plot that calls ScaledPlot); it allows easy
	specification of scales to be used for tick marks and
	grid lines.
*)

tickopts[xfun_, yfun_, deffunc_, opts_] :=
	Module[{tick, frame, grid},
		{tick, frame, grid} = {Ticks, FrameTicks, GridLines}/.
			opts/.Options[deffunc];
		{Ticks -> If[tick === Automatic,
			{xfun,yfun},
			tick],
		FrameTicks -> If[frame === Automatic,
			{xfun, yfun, xfun, yfun},
			frame],
		GridLines -> If[grid === Automatic,
			{If[xfun === Automatic,
				xfun,
				(Map[First, xfun[#1,#2]] &)],
			If[yfun === Automatic,
				yfun,
				(Map[First, yfun[#1,#2]] &)]},
			grid]}
	]

(* scaleplotrange is an auxilliary hack to fix the plot range problem;
	the range should be in scaled coordinates, not in original coordinates.
	This transforms them, with a separate transformation defined for each
	function.  Not the ideal solution, but sufficient as a kludge... note
	that this introduces incompatability with any code that uses the old
	plot ranges...
*)

scaleplotrange[type:(LogPlot | LinearLogPlot | LogListPlot | LinearLogListPlot),
		options_] :=
	PlotRange -> Replace[PlotRange/.options/.Options[type],
			{{x_List, y_List} -> {x,Log[10,y]},
			y_List -> Log[10,y]}]

scaleplotrange[type:(LogLinearPlot | LogLinearListPlot),
		options_] :=
	PlotRange -> Replace[PlotRange/.options/.Options[type],
			{x_List, y_List} -> {Log[10,x],y}]

scaleplotrange[type:(LogLogPlot | LogLogListPlot),
		options_] :=
	PlotRange -> Replace[PlotRange/.options/.Options[type],
			y_List -> Log[10,y]]

(* Scaled Plot *)

Options[ScaledPlot] =
	{Scale -> (# &), DisplayFunction :> $DisplayFunction};

ScaledPlot[funcs_List,{x_Symbol,xmin_,xmax_},opts___] :=
	Module[{scale,g,r,popts, xs, ys, disp,ao},
		{scale, disp,ao} = {Scale, DisplayFunction, AxesOrigin}/.
			{opts}/.Options[ScaledPlot];
		popts = FilterOptions[ParametricPlot, opts];
		If[Head[scale] =!= List,
			scale = {scale, scale}
		];
		If[Length[scale] > 2,
			scale = Take[scale,2]
		];
		{xs, ys} = scale;
		g = ParametricPlot[
			Evaluate[
				Map[{xs[x], ys[#]}&,
					funcs],
				{x, xmin, xmax},
			DisplayFunction -> Identity,
			popts]];
		r = PlotRange[g];
		If[ao === Automatic,
			ao = Map[#[[1]]&,r],
			ao = {xs[First[ao]], ys[Last[ao]]}
		];
		Show[g, DisplayFunction -> disp,
			PlotRange -> r,
			AxesOrigin -> ao
		]
	]

ScaledPlot[f_, range_, opts___] :=
	ScaledPlot[{f}, range, opts]

(* Scaled List Plot *)

Options[ScaledListPlot] =
	{Scale -> (# &), DisplayFunction :> $DisplayFunction};

ScaledListPlot[data:{{_?numberQ,_?numberQ}..}, opts___] :=
	Module[{scale, g, r, xs, ys, lopts, disp, ao},
		{scale, disp, ao} = {Scale, DisplayFunction, AxesOrigin}/.
			{opts}/.Options[ScaledPlot];
		lopts = FilterOptions[ListPlot, opts];
		If[Head[scale] =!= List,
			scale = {scale, scale}
		];
		If[Length[scale] > 2,
			scale = Take[scale,2]
		];
		{xs, ys} = scale;
		g = ListPlot[
				Map[{xs[ #[[1]] ], ys[ #[[2]] ]}&,
					data],
			DisplayFunction -> Identity,
			lopts];
		r = PlotRange[g];
		If[ao === Automatic,
			ao = Map[#[[1]]&,r],
			ao = {xs[First[ao]], ys[Last[ao]]}
		];
		Show[g, DisplayFunction -> disp,
			PlotRange -> r,
			AxesOrigin -> ao
		]
	]

ScaledListPlot[data:{_?numberQ..}, opts___] :=
	ScaledListPlot[Transpose[{Range[Length[data]],data}], opts]

(* PolarPlot  *)

SetAttributes[PolarPlot, HoldAll]

PolarPlot[r_List, {t_, tmin_, tmax_}, opts___] :=
	ParametricPlot[Evaluate[Transpose[{r Cos[t], r Sin[t]}]],
		{t, tmin, tmax}, opts, AspectRatio->Automatic]

PolarPlot[r_, {t_, tmin_, tmax_}, opts___] :=
	ParametricPlot[{r Cos[t], r Sin[t]}, {t, tmin, tmax}, opts,
		AspectRatio->Automatic]

(* PolarListPlot *)

PolarListPlot[rlist_List, opts___] :=
	ListPlot[ rlist * Map[{Cos[#], Sin[#]}&, 
			2Pi/Length[rlist] Range[0, Length[rlist]-1]], 
	opts, AspectRatio->Automatic ]

(* ErrorListPlot *)

ErrorListPlot[l2:{{_, _}..}] :=
        Module[ {i}, 
	ErrorListPlot[ Table[Prepend[l2[[i]], i], {i, Length[l2]}] ] ]

ErrorListPlot[l3:{{_, _, _}..}] :=
        Show[ Graphics[ { PointSize[0.015], Thickness[0.002],
                Module[ {i, x, y, dy} , 
                Table[ 
                        {x, y, dy} = l3[[i]] ;
                        { Line[ {{x, y-dy}, {x, y+dy}} ],
                        Point[ {x, y} ] } ,
                        {i, Length[l3]}
                ] ] } ], Axes -> Automatic ]

(* DisplayTogether and DisplayTogetherArray.  These take a series of plot commands,
	and combine the resulting graphics to produce a single graphic, rather
	than the output of the individual commands.  The constraint is that
	the plot commands must all accept the option DisplayFunction->Identity,
	and all commands must be able to be shown together via Show.  Note
	that this second constraint is not present for DisplayTogetherArray, since
	it produces a GraphicsArray as output.
*)

Attributes[DisplayTogether] = {HoldAll};

DisplayTogether[plots__, opts:(_Rule | _RuleDelayed)...] :=
	Show[insertoption[{plots}, DisplayFunction -> Identity],
		opts, DisplayFunction -> $DisplayFunction]

Attributes[DisplayTogetherArray] = {HoldAll};

DisplayTogetherArray[plotarray_List,opts:(_Rule | _RuleDelayed)...] :=
	Show[GraphicsArray[insertoption[plotarray,
			DisplayFunction -> Identity]],
		opts, DisplayFunction -> $DisplayFunction]

DisplayTogetherArray[plots__,opts:(_Rule | _RuleDelayed)...] :=
	Show[GraphicsArray[insertoption[{plots},
			DisplayFunction -> Identity]],
		opts, DisplayFunction -> $DisplayFunction]

Attributes[insertoption] = {HoldFirst, Listable};

insertoption[thing_,option_] :=
	Module[{gtype, list, rpos},
		gtype = ReleaseHold[HeldPart[Hold[thing],1,0]];
		list = ReleaseHold[ReplaceHeldPart[Hold[thing],
					List, {1, 0}]];
		rpos = Position[list,(_Rule | _RuleDelayed), {1},
					Heads -> False];
		If[rpos === {},
			gtype @@ Append[list,option],
			gtype @@ Insert[list,option,First[rpos]]
		]
	]

(* List and Curve Plot.  This function generates plots combining
data and curves. *)

Options[ListAndCurvePlot] =
	{PlotStyle -> Automatic};

ListAndCurvePlot[data__,range:{_Symbol,_,_},
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{ps, lpopts, popts, gopts},
		{ps} = {PlotStyle}/.{opts}/.Options[ListAndCurvePlot];
		lpopts = FilterOptions[ListPlot,opts];
		popts = FilterOptions[Plot, opts];
		gopts = FilterOptions[Graphics, opts];
		If[ps === Automatic || ps === {},
			ps = {GrayLevel[0]}];
		ps = CycleValues[ps, Length[{data}]];
		plots = MapThread[If[MatchQ[#1,{__?(NumberQ[N[#]]&)} |
					{{__?(NumberQ[N[#]]&)}..}],
				ListPlot[#1, DisplayFunction -> Identity,
						PlotStyle -> #2, lpopts],
				Plot[#1, range, DisplayFunction -> Identity,
						PlotStyle -> {#2}, Evaluate[popts]]
				]&,
			{{data},ps}];
		Show[plots, gopts, DisplayFunction -> $DisplayFunction]
	]

(* BarCharts -
	BarChart, GeneralizedBarChart, StackedBarChart, PercentileBarChart.
	with the internal RectanglePlot and small utilities *)

(* RectanglePlot *)

Options[RectanglePlot] =
	{RectangleStyle -> Automatic,
	EdgeStyle -> Automatic,
	ObscuredFront -> False};

RectanglePlot[boxes:{{{_?numberQ,_?numberQ},{_?numberQ,_?numberQ}}..},
		opts___] :=
	Module[{ln = Length[boxes], bsytle, estyle, gopts},
	(* Handle options and defaults *)
		{bstyle, estyle,sort} = {RectangleStyle, EdgeStyle,
			ObscuredFront}/.{opts}/.
			Options[RectanglePlot];
		gopts = FilterOptions[Graphics, opts];
		If[bstyle === Automatic,
			bstyle = Map[Hue,.6 Range[0, ln - 1]/(ln - 1)]];
		If[bstyle === None, bstyle = {}];
		If[estyle === Automatic, estyle = {GrayLevel[0]}];
		If[estyle === None, estyle = {}];
		bstyle = CycleValues[bstyle,ln];
		estyle = CycleValues[estyle,ln];
	(* generate shapes *)
		recs = If[bstyle === {},
			Table[{},{ln}],
			Transpose[{bstyle, Apply[Rectangle, boxes,{1}]}]];
		lrecs = If[estyle === {},
			Table[{},{ln}],
			Transpose[{estyle, Map[LineRectangle, boxes]}]];
	(* sort 'em *)
		recs = Map[Flatten,
			If[TrueQ[sort],
				Sort[Transpose[{recs,lrecs}], coversQ],
				Transpose[{recs, lrecs}]
			],
			{2}
		];
	(* show 'em *)
		Show[Graphics[recs],gopts]
	]

RectanglePlot[boxes:{{_?numberQ,_?numberQ}..}, opts___] :=
	RectanglePlot[Map[{#, # + 1}&,boxes],opts]

LineRectangle[pts:{{x1_,y1_}, {x2_,y2_}}] :=
	Line[{{x1,y1},{x1,y2},{x2,y2},{x2,y1},{x1,y1}}]

coversQ[{{___,Rectangle[{x11_,y11_}, {x12_,y12_}]},___},
		{{___,Rectangle[{x21_,y21_}, {x22_,y22_}]},___}] :=
	N[And[x11 <= x21 <= x12,
		x11 <= x22 <= x12,
		y11 <= y21 <= y12,
		y11 <= y22 <= y12]]

coversQ[___] := True

(* Bar Chart *)

Clear[BarChart]

Options[BarChart] =
	{BarStyle -> Automatic,
	BarSpacing -> Automatic,
	BarGroupSpacing -> Automatic,
	BarLabels -> Automatic,
	BarValues -> False,
	BarEdges -> True,
	BarEdgeStyle -> GrayLevel[0],
	BarOrientation -> Vertical};

BarChart[idata:{_?numberQ..}..,
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{data, ln = Length[{idata}], ticks, orig,rng,
			lns = Map[Length,{idata}], bs, bgs, labels, width,gbopts},
		{bs,bgs,labels,orient} = {BarSpacing, BarGroupSpacing,
			BarLabels, BarOrientation}/.
			{opts}/.Options[BarChart];
		gbopts = FilterOptions[GeneralizedBarChart,
			Sequence @@ Options[BarChart]];
		bs = N[bs]; bgs = N[bgs];
		If[bs === Automatic, bs = 0];
		If[bgs === Automatic, bgs = .2];
		Which[labels === Automatic,
				labels = Range[Max[lns]],
			labels === None,
				Null,
			True,
				labels = CycleValues[labels,Max[lns]]
		];
		width = (1 - bgs)/ln;
		data = MapIndexed[
			{#2[[2]] + width (#2[[1]] - 1), #1, width - bs}&,
			{idata},{2}];
		If[labels =!= None,
			ticks = {Transpose[{
						Range[Max[lns]] + (ln - 1)/2 width,
						labels}],
					Automatic},
		(* else *)
			ticks = {None, Automatic};
		];
		orig = {1 - width/2 - bgs,0};
		rng = {{1 - width/2 - bgs,
					Max[lns] + (ln - 1/2) width + bgs},
				Automatic};
		If[orient === Horizontal,
			ticks = Reverse[ticks]; orig = Reverse[orig];
			rng = Reverse[rng]];
		GeneralizedBarChart[Sequence @@ data, opts,
			Ticks -> ticks,
			AxesOrigin -> orig,
			PlotRange -> rng,
			FrameTicks -> ticks,
			gbopts]
	]

(* For compatability only... *)

BarChart[list:{{_?numberQ, _}..},
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{lab,dat},
		{dat, lab} = Transpose[list];
		BarChart[dat, opts, BarLabels -> lab]
	]

BarChart[list:{{_?numberQ, _, _}..},
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{lab, sty, dat},
		{dat, lab, sty} = Transpose[list];
		BarChart[dat, opts, BarLabels -> lab, BarStyle -> sty]
	]

(* GeneralizedBarChart *)

Options[GeneralizedBarChart] =
	{BarStyle -> Automatic,
	BarValues -> False,
	BarEdges -> True,
	BarEdgeStyle -> GrayLevel[0],
	BarOrientation -> Vertical};

GeneralizedBarChart::badorient =
"The value given for BarOrientation is invalid; please use
Horizontal or Vertical. The chart will be generated with
Vertical.";

GeneralizedBarChart[idata:{{_?numberQ,_?numberQ,_?numberQ}..}..,
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{data = {idata}, bsty, val, vpos, unob, edge, esty, bsf,
			orient, ln = Length[{idata}],
			lns = Map[Length,{idata}], bars, disp},
	(* Get options *)
		{bsty, val, edge, esty, orient} =
			{BarStyle, BarValues, BarEdges, BarEdgeStyle,
			BarOrientation}/.{opts}/.Options[GeneralizedBarChart];
		gopts = FilterOptions[Graphics,opts];
		disp = DisplayFunction/.{opts}/.Options[Graphics];
	(* Handle defaults and error check options *)
		If[bsty =!= Automatic && Head[bsty] =!= List,
			bsty = Join @@ Map[bsty[#[[2]]]&,data,{2}],
			bsty = barcoloring[bsty, ln, lns]
		];
		If[TrueQ[edge],
			If[ln === 1,
				esty = CycleValues[esty, Length[First[data]]],
				esty = Join @@ MapThread[Table[#1,{#2}]&,
					{CycleValues[esty,ln], lns}]
			],
			esty = None
		];
		If[!MemberQ[{Horizontal, Vertical},orient],
			Message[GeneralizedBarChart::badorient,orient];
				orient = Vertical
		];
		val = TrueQ[val];
		vpos = .05;   (* was an option, position of value label; now hardcoded at
						swolf recommendation. *)
	(* generate bars and labels, call RectanglePlot *)
		data = Flatten[data,1];
		bars = Map[barcoords[orient],data];
		If[val,
			Show[RectanglePlot[bars,
					RectangleStyle -> bsty,
					EdgeStyle -> esty,
					DisplayFunction -> Identity],
				Graphics[Map[varcoords[orient,vpos,(#&)],data]],
				Axes -> True,
				DisplayFunction -> disp,
				gopts,
				PlotRange -> All
			],
		(* else *)
			RectanglePlot[bars,
				RectangleStyle -> bsty,
					EdgeStyle -> esty,
					ObscuredFront -> unob,
					gopts,
					Axes -> True]
		]
	]

barcoords[Horizontal][{pos_,len_,wid_}] :=
	{{0,pos - wid/2},{len,pos + wid/2}}

barcoords[Vertical][{pos_,len_,wid_}] :=
	{{pos - wid/2, 0},{pos + wid/2, len}}

varcoords[Horizontal,offset_,format_][{pos_,len_,wid_}] :=
	Text[format[len], Scaled[{Sign[len] offset, 0}, {len, pos}]]

varcoords[Vertical,offset_,format_][{pos_,len_,wid_}] :=
	Text[format[len], Scaled[{0,Sign[len] offset}, {pos,len}]]

barcoloring[Automatic, 1, _] := {Hue[0]}

barcoloring[Automatic, ln_, lns_] :=
	Join @@ MapThread[Table[#1,{#2}]&,
		{Map[Hue[.6 #/(ln - 1)]&, Range[0, ln - 1]], lns}]

barcoloring[bsty_, 1, lns_] :=
	CycleValues[bsty, First[lns]]

barcoloring[bsty_, ln_, lns_] :=
	Join @@ MapThread[Table[#1,{#2}]&,
				{CycleValues[bsty, ln], lns}]

(* StackedBarChart *)

Options[StackedBarChart] =
	{BarStyle -> Automatic,
	BarSpacing -> Automatic,
	BarLabels -> Automatic,
	BarEdges -> True,
	BarEdgeStyle -> GrayLevel[0],
	BarOrientation -> Vertical};

StackedBarChart::badorient =
"The value given for BarOrientation is invalid; please use
Horizontal or Vertical. The chart will be generated with
Vertical.";

StackedBarChart::badspace =
"The value `1` given for the BarSpacing option is invalid;
please enter a number or Automatic.";

StackedBarChart[idata:{_?numberQ..}..,
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{data = {idata}, sty, space, labels, bv, bvp, edge,
			esty, orient, ln = Length[{idata}], add, tmp,
			lns = Map[Length,{idata}],ticks,orig,rng},
	(* process options *)
		{sty, space, labels, edge, esty, orient} =
			{BarStyle, BarSpacing, BarLabels,
			BarEdges, BarEdgeStyle,
			BarOrientation}/.{opts}/.Options[StackedBarChart];
		sty = barcoloring[sty, ln, lns];
		If[TrueQ[edge],
			If[ln === 1,
				esty = CycleValues[esty, First[lns]],
				esty = Join @@ MapThread[Table[#1,{#2}]&,
					{CycleValues[esty,ln], lns}]
			],
			esty = None
		];
		If[!MemberQ[{Horizontal, Vertical},orient],
			Message[StackedBarChart::badorient,orient];
				orient = Vertical
		];
		Which[labels === Automatic,
				labels = Range[Max[lns]],
			labels === None,
				Null,
			True,
				labels = CycleValues[labels,Max[lns]]
		];
		If[!(numberQ[space] || (space === Automatic)),
			Message[StackedBarChart::badspace, space];
			space = Automatic];
		If[space === Automatic, space = .2];
		If[labels =!= None,
			ticks = {Transpose[{
						Range[Max[lns]],
						labels}],
					Automatic},
		(* else *)
			ticks = {None, Automatic};
		];
		orig = {1/2,0};
		rng = {{1/2,Max[lns] + 1/2}, Automatic};
			(* data to rectangles *)
		halfwidth = (1 - space)/2; width = (1 - space);
		ends = Table[{0,0},{Max[lns]}];
		data = Map[
			MapIndexed[
				(If[Negative[N[#1]],
					add = {0, #1};
					tmp = {First[#2] - halfwidth,
						Last[ends[[ First[#2] ]] ]},
					(* else *)
					add = {#1, 0};
					tmp = {First[#2] - halfwidth,
						First[ends[[ First[#2] ]] ]}
				];
				ends[[ First[#2] ]] += add;
				{tmp, tmp + {width, N[#1]}})&,
			#]&,
			data
		];
		If[orient === Horizontal,
			ticks = Reverse[ticks]; orig = Reverse[orig];
			rng = Reverse[rng];
			data = Map[Reverse,data,{3}]];
	(* plot 'em! *)
		RectanglePlot[Flatten[data,1],
			RectangleStyle -> sty,
			EdgeStyle -> esty,
			opts,
			Axes -> True,
			AxesOrigin -> orig,
			PlotRange -> rng,
			Ticks -> ticks,
			FrameTicks -> ticks]

	]

(* PercentileBarChart *)

Options[PercentileBarChart] =
	{BarStyle -> Automatic,
	BarSpacing -> Automatic,
	BarLabels -> Automatic,
	BarEdges -> True,
	BarEdgeStyle -> GrayLevel[0],
	BarOrientation -> Vertical};

PercentileBarChart[idata:{_?numberQ..}..,
		opts:((_Rule | _RuleDelayed)...)] :=
	Module[{data = {idata}, labels,
			orient, ln = Length[{idata}],
			lns = Map[Length,{idata}],xticks, yticks, ticks},
	(* options and default processing *)
		{labels, orient} = {BarLabels, BarOrientation}/.
			{opts}/.Options[PercentileBarChart];
		Which[labels === Automatic,
				labels = Range[Max[lns]],
			labels === None,
				Null,
			True,
				labels = CycleValues[labels,Max[lns]]
		];
		If[labels =!= None,
			xticks = Transpose[{Range[Max[lns]],labels}],
			xticks = Automatic
		];
		If[MemberQ[ Flatten[Sign[N[data]]], -1],
			yticks = Transpose[{
				Range[-1,1,.2],
				Map[ToString[#] <> "%"&,Range[-100,100,20]]}],
			yticks = Transpose[{
				Range[0,1,.1],
				Map[ToString[#] <> "%"&, Range[0,100,10]]}]
		];
		If[orient === Horizontal,
			ticks = {yticks, xticks},
			ticks = {xticks, yticks}
		];
	(* process data - convert to percentiles *)
		data = Map[pad[#,Max[lns]]&, data];
		maxs = Apply[Plus, Transpose[Abs[data]],{1}];
		data = Map[MapThread[If[#2 == 0, 0, #1/#2]&,{#,maxs}]&,
			data];
	(* plot it! *)
		StackedBarChart[Sequence @@ data,
			opts,
			Ticks -> ticks,
			FrameTicks -> ticks,
			Sequence @@ Options[PercentileBarChart]
		]
	]

pad[list_, length_] := list/; Length[list] === length

pad[list_,length_] :=
	Join[list, Table[0,{length - Length[list]}]]

(* Pie Chart *)

Options[PieChart] =
	{PieLabels -> Automatic,
	PieStyle -> Automatic,
	PieLineStyle -> Automatic,
	PieExploded -> None};

(* The following line is for compatability purposes only... *)

PieChart[list:{{_?((numberQ[#] && NonNegative[N[#]])&), _}..}, opts___] :=
	PieChart[First[Transpose[list]],
		PieLabels->Last[Transpose[list]],opts]

PieChart[list:{_?((numberQ[#] && NonNegative[N[#]])&) ..}, opts___] :=
	Module[ {labels, styles, linestyle, tlist, thalf, text,offsets,halfpos,
				len = Length[list],exploded,wedges,angles1,angles2,lines,
				tmp},
	(* Get options *)
		{labels, styles, linestyle,exploded} =
			{PieLabels, PieStyle, PieLineStyle,PieExploded}/.
			{opts}/.Options[PieChart];
		gopts = FilterOptions[Graphics, opts];
	(* Error handling on options, set defaults *)
		If[Head[labels] =!= List || Length[labels] === 0,
			If[labels =!= None, labels = Range[len]],
			labels = CycleValues[labels, len]
		];
		If[Head[styles] =!= List || Length[styles] === 0,
			styles = Map[Hue, (Range[len] - 1)/(len - 1) .7],
			styles = CycleValues[styles, len]
		];
		If[linestyle === Automatic, linestyle = GrayLevel[0]];
		If[MatchQ[exploded,{_Integer,_Real}],exploded = {exploded}];
		If[exploded === None, exploded = {}];
		If[exploded === All,
			exploded = Range[len]];
		If[(tmp = DeleteCases[exploded,
				(_Integer | {_Integer,_?(NumberQ[N[#]]&)})]) =!= {},
			Message[PieChart::badexplode,tmp];
			exploded = Cases[exploded,
				(_Integer | {_Integer,_?(NumberQ[N[#]]&)})]
		];
		exploded = Map[If[IntegerQ[#], {#,.1},#]&,exploded];
		offsets = Map[If[(tmp = Cases[exploded,{#,_}]) =!= {},
				Last[First[tmp]],
				0]&,
			Range[len]
		];
	(* Get range of values, set up list of thetas *)
		tlist = N[ 2 Pi FoldList[Plus,0,list]/(Plus @@ list)];
	(* Get pairs of angles *)
		angles1 = Drop[tlist,-1];angles2 = Drop[tlist,1];
	(* bisect pairs (for text placement and offsets) *)
		thalf = 1/2 (angles1 + angles2);
		halfpos = Map[{Cos[#],Sin[#]}&,thalf];
	(* generate lines, text, and wedges *)
		text = If[labels =!= None,
			MapThread[Text[#3,(#1 + .6) #2]&,
					{offsets,halfpos,labels}],
				{}];
		lines = MapThread[{
				Line[{#1 #2,{Cos[#3],Sin[#3]} + #1 #2}],
				Line[{#1 #2,{Cos[#4],Sin[#4]} + #1 #2}],
				Circle[#1 #2,1,{#3,#4}]}&,
			{offsets,halfpos,angles1,angles2}];
		wedges = MapThread[
				Flatten[{#5, Disk[#1 #2, 1, {#3,#4}]}]&,
			{offsets,halfpos,angles1,angles2,styles}];
	(* show it all... *)
		Show[Graphics[
			{wedges,
			Flatten[{linestyle, lines}],
			text},
			AspectRatio->Automatic, gopts]]
	]

(* TransformGraphics *)

TransformGraphics[Graphics[list_, opts___], f_] :=
	Graphics[ TG0[list, f], opts ]

TG0[d_List, f_] := Map[ TG0[#, f]& , d ]

TG0[Point[d_List], f_] := Point[f[d]]

TG0[Line[d_List], f_] := Line[f /@ d]

TG0[Rectangle[{xmin_, ymin_}, {xmax_, ymax_}], f_] :=
	TG0[Polygon[{{xmin,ymin}, {xmin,ymax}, {xmax, ymax}, {xmax, ymin}}], f]

TG0[Polygon[d_List], f_] := Polygon[f /@ d]

TG0[Circle[d_List, r_?numberQ, t___], f_] :=
	Circle[f[d], f[{r,r}], t]

TG0[Circle[d_List, r_List, t___], f_] :=
        Circle[f[d], f[r], t] 

TG0[Disk[d_List, r_?numberQ, t___], f_] :=
        Disk[f[d], f[{r,r}], t] 

TG0[Disk[d_List, r_List, t___], f_] := 
        Disk[f[d], f[r], t]

TG0[Raster[array_, range_List:{{0,0}, {1,1}}, zrange___], f_] := 
	Raster[array, f /@ range, zrange]

TG0[RasterArray[array_, range_List:{{0,0}, {1,1}}, zrange___], f_] := 
	RasterArray[array, f /@ range, zrange]

TG0[Text[expr_, d_List, opts___], f_] := Text[expr, f[d], opts]

TG0[expr_, f_] := expr

(* SkewGraphics *)

SkewGraphics[g_, m_?MatrixQ] :=
	TransformGraphics[g, (m . #)&]

End[ ]   (* Graphics`Graphics`Private` *)

EndPackage[ ]   (* Graphics`Graphics` *)


(*:Limitations: none known. *)

(*:Tests:

*)

(*:Examples:

LinearScale[ 1,2]

LogScale[1,10]

UnitScale[2,10,0.7]

PiScale[ 0,10]

TextListPlot[{{1.5, 2.5}, {1.6, 2.6}, {1.7, 2.7}, {1.8, 2.8}}]

TextListPlot[{ {1.5,2.5,1},{1.6,2.6,2},{1.7,2.7,3},{1.8,2.8,4}}]

LabeledListPlot[{ {1.5,2.5,1},{1.6,2.6,2},{1.7,2.7,3},{1.8,2.8,4}}]

LogPlot[ Sin[x],{x,0.1,3.1}]

LogPlot[ Exp[ 4 x], {x,1,5}, Frame -> True]

LogPlot[ Exp[ 4 x], {x,1,5}, Frame -> True,
	GridLines -> {Automatic, LogGridMajor}]

LogPlot[ Exp[ 4 x], {x,1,3}, Frame -> True,
	GridLines -> {Automatic, LogGridMinor}]

LogListPlot[ Table[i,{i,10}] ]

LogListPlot[ Table[ {i/2,i^2},{i,20}]]

LogLogPlot[ Sin[x],{x,0.1,3.1}]

LogLogListPlot[ Table[ i^2,{i,10}]]

LogLogListPlot[ Table[ {i^2,i^3},{i,10}]]

PolarPlot[ Cos[t], {t,0,2 Pi}]

PolarPlot[ {Cos[t], Sin[2 t]},{t,0,2 Pi}]

PolarListPlot[ Table[ {t/2,Cos[t]},{t,0,2 Pi, .1}]]

ErrorListPlot[Table[ { i,i^2},{i,10}]]

ErrorListPlot[ Table[ { Sin[t],Cos[t], t},{t,10}]]

data = Table[{n/15,(n/15)^2 = 2 + Random[Real, {-.3,.3}]},
		{n,15}]; fit = Fit[data,{1,x,x^2},x];
ListAndCurvePlot[data,fit,{x,0,1}]

BarChart[ Table[i,{i,1,10}]]

BarChart[ Table[ {Sin[t], SIN[t]},{t,0.6,3,0.6}]]

PieChart[ Table[ i,{i,5}]]

PieChart[ Table[ {i,A[i]},{i,7}]]

Show[GraphicsArray[
	{{PieChart[{.2,.3,.1},DisplayFunction->Identity],
	PieChart[{.2,.3,.1},PieExploded->All,
		DisplayFunction->Identity],
	PieChart[{.2,.3,.1},PieExploded->{3,.2},
		DisplayFunction->Identity]}}],
	DisplayFunction->$DisplayFunction]

PlotStyle[Plot[Sin[x],{x,0,Pi}]]

PlotStyle[Plot[Sin[x],{x,0,Pi},
	PlotStyle->{{Dashing[{.02,.02}],Thickness[.007]}}]]

g1 = Plot[t,{t,0,Pi}]; Show[ TransformGraphics[ g1, Sin[#]& ] ]

g1 = Plot[ Sin[t],{t,0,Pi}]; Show[ SkewGraphics[g1, {{1,2},{0,1}}]]

*)

