void
TestData
	(
	Test2DPlotDirector* dir
	)
{
JIndex i;

	JX2DPlotWidget* plot = dir->GetPlotWidget();
	plot->ShowLegend();

	JArray<JFloat> x(100),y(100), xPErr(101),xMErr(101), yPErr(101), yMErr(101);
	JKLRand r;

	JFloat delta = kJPi/50.0;
	for (i=0; i<=100; i++)
		{
		x.AppendElement(i*delta);
		y.AppendElement(sin(i*delta));

		xPErr.AppendElement(r.UniformDouble(0.0, 0.1));
		xMErr.AppendElement(r.UniformDouble(0.0, 0.1));
		yPErr.AppendElement(r.UniformDouble(0.0, 0.1));
		yMErr.AppendElement(r.UniformDouble(0.0, 0.1));
		}

	J2DPlotData* data;
	JBoolean ok = J2DPlotData::Create(&data, x, y, kJFalse);
	assert( ok );
	ok = data->SetXErrors(xPErr, xMErr);
	assert( ok );
	ok = data->SetYErrors(yPErr, yMErr);
	assert( ok );

	plot->AddCurve(data, kJTrue, "sin(x)", kJTrue, kJTrue);

	x.RemoveAll();
	y.RemoveAll();

	delta = kJPi/5000.0;
	for (i=0; i<=10000; i++)
		{
		x.AppendElement(i*delta);
		y.AppendElement(cos(i*delta));
		}

	plot->AddCurve(x, y, kJFalse, "cos(x)", &i, kJTrue, kJFalse);

	plot->SetTitle("Error bars");
}
void
PlotDir::WriteCurves
	(
	std::ostream& os,
	GRaggedFloatTableData* data
	)
{
	const JSize tempCount = itsPlot->GetCurveCount();
	JSize count = 0;
	JSize i;
	for (i = 1; i <= tempCount; i++)
		{
		JPlotDataBase& jpdb = itsPlot->GetCurve(i);
		CurveStats stat = itsCurveStats->GetElement(i);
		if ((stat.type == kGDataCurve) && (jpdb.GetType() == JPlotDataBase::kScatterPlot))
			{
			J2DPlotData* pd = dynamic_cast<J2DPlotData*>(&jpdb);
			assert( pd != NULL );
			if (pd->IsValid())
				{
				count++;
				}
			}
		else if (stat.type == kGFitCurve)
			{
			JPlotDataBase& pdb = itsPlot->GetCurve(stat.provider);
			J2DPlotData* pd = dynamic_cast<J2DPlotData*>(&pdb);
			assert( pd != NULL );
			if (pd->IsValid())
				{
				count++;
				}
			}
		else
			{
			count++;
			}
		}

	os << count << ' ';
	for (i = 1; i <= tempCount; i++)
		{
		JPlotDataBase& jpdb = itsPlot->GetCurve(i);
		CurveStats stat = itsCurveStats->GetElement(i);
		if (stat.type == kGDataCurve)
			{
			if (jpdb.GetType() == JPlotDataBase::kScatterPlot)
				{
				J2DPlotData* pd = dynamic_cast<J2DPlotData*>(&jpdb);
				assert( pd != NULL );
				if (pd->IsValid())
					{
					os << (int)kGDataCurve << ' ';
					os << (int)jpdb.GetType() << ' ';
					JIndex index;
					data->FindColumn(const_cast< JArray<JFloat>* >(&(pd->GetXData())), &index);
					os << index << ' ';
					data->FindColumn(const_cast< JArray<JFloat>* >(&(pd->GetYData())), &index);
					os << index << ' ';
					os << pd->HasXErrors() << ' ';
					os << pd->HasYErrors() << ' ';
					if (pd->HasXErrors())
						{
						const JArray<JFloat>* testArray;
						pd->GetXPErrorData(&testArray);
						data->FindColumn(testArray, &index);
						os << index << ' ';
						}
					if (pd->HasYErrors())
						{
						const JArray<JFloat>* testArray;
						pd->GetYPErrorData(&testArray);
						data->FindColumn(testArray, &index);
						os << index << ' ';
						}
					}
				}
			else if (jpdb.GetType() == JPlotDataBase::kVectorPlot)
				{
				J2DVectorData* vd = dynamic_cast<J2DVectorData*>(&jpdb);
				assert( vd != NULL );
				os << (int)kGDataCurve << ' ';
				os << (int)jpdb.GetType() << ' ';
				JIndex index;
				const JArray<JFloat>* carray;
				carray	= &(vd->GetXData());
				JArray<JFloat>* array = const_cast< JArray<JFloat>* >(carray);
				data->FindColumn(array, &index);
				os << index << ' ';
				carray	= &(vd->GetYData());
				array = const_cast< JArray<JFloat>* >(carray);
				data->FindColumn(array, &index);
				os << index << ' ';
				carray	= &(vd->GetVXData());
				array = const_cast< JArray<JFloat>* >(carray);
				data->FindColumn(array, &index);
				os << index << ' ';
				carray	= &(vd->GetVYData());
				array = const_cast< JArray<JFloat>* >(carray);
				data->FindColumn(array, &index);
				os << index << ' ';
				}
			}
		else if (stat.type == kGFitCurve)
			{
			if (stat.fitType == kGModFit)
				{
				os << (int)kGFitCurve << ' ';
				os << (int)stat.fitType << ' ';
				os << stat.provider << ' ';
				JPlotModuleFit* mf = dynamic_cast<JPlotModuleFit*>(&jpdb);
				assert( mf != NULL );
				mf->WriteData(os);
				}
			else
				{
				JPlotDataBase& pdb = itsPlot->GetCurve(stat.provider);
				J2DPlotData* pd = dynamic_cast<J2DPlotData*>(&pdb);
				assert( pd != NULL );
				if (pd->IsValid())
					{
					os << (int)kGFitCurve << ' ';
					os << (int)stat.fitType << ' ';
					os << stat.provider << ' ';

					if (stat.fitType == kGProxyFit)
						{
						JPlotFitProxy* pf	= dynamic_cast<JPlotFitProxy*>(&jpdb);
						assert(pf != NULL);
						pf->WriteData(os);
						}
					}
				}
			}
		else if (stat.type == kGFunctionCurve)
			{
			J2DPlotJFunction* pd = dynamic_cast<J2DPlotJFunction*>(&jpdb);
			assert( pd != NULL );
			os << (int)kGFunctionCurve << ' ';
			os << pd->GetFunctionString() << ' ';
			}
		else
			{
			os << (int)kGDiffCurve << ' ';
			}
		}
}
JPlotFitProxy::JPlotFitProxy
	(
	JPlotFitFunction*	fit,
	J2DPlotWidget* 		plot, 
	JPlotDataBase* 		fitData
	)
	:
	JPlotFitFunction(plot, fitData, 0, 0),
	itsErrors(NULL),
	itsHasGOF(fit->HasParameterErrors()),
	itsGOFName(fit->HasGoodnessOfFit()),
	itsFnString(fit->GetFitFunctionString())
{
	if (itsHasGOF)
		{
		fit->GetGoodnessOfFitName(&itsGOFName);
		fit->GetGoodnessOfFit(&itsGOF);
		}
	itsParms	= new GVarList();
	assert(itsParms != NULL);
	itsParms->AddVariable("x", 0);
	const JSize count	= fit->GetParameterCount();
	SetParameterCount(count);
	for (JIndex i = 1; i <= count; i++)
		{
		JString name;
		JBoolean ok	= fit->GetParameterName(i, &name);
		assert(ok);
		JFloat value;
		ok	= fit->GetParameter(i, &value);
		assert(ok);
		itsParms->AddVariable(name, value);
		}

	if (fit->HasParameterErrors())
		{
		SetHasParameterErrors(kJTrue);
		itsErrors	= new JArray<JFloat>;
		assert(itsErrors != NULL);
		for (JIndex i = 1; i <= count; i++)
			{
			JFloat value;
			JBoolean ok	= fit->GetParameterError(i, &value);
			assert(ok);
			itsErrors->AppendElement(value);
			}
		}

	J2DPlotData* diff	= fit->GetDiffData();
	J2DPlotData* data;
	if (J2DPlotData::Create(&data, diff->GetXData(), diff->GetYData(), kJFalse))
		{
		const JArray<JFloat>* xerrors;
		if (diff->GetXPErrorData(&xerrors))
			{
			data->SetXErrors(*xerrors);
			}
		const JArray<JFloat>* yerrors;
		if (diff->GetYPErrorData(&yerrors))
			{
			data->SetYErrors(*yerrors);
			}
		SetDiffData(data);
		}
	JFloat xMin;
	JFloat xMax;
	fit->GetXRange(&xMin, &xMax);
	SetXRange(xMin, xMax);
	itsFn	= NULL;
	JParseFunction(itsFnString, itsParms, &itsFn);
	SetHasGoodnessOfFit(itsHasGOF);
}