1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 #include "StatisticsHelper.hxx"
31 #include "DataSeriesHelper.hxx"
32 #include "ErrorBar.hxx"
35 #include <rtl/math.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <comphelper/processfactory.hxx>
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
41 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
42 #include <com/sun/star/chart2/data/XDataSink.hpp>
43 #include <com/sun/star/chart/ErrorBarStyle.hpp>
45 using ::com::sun::star::uno::Sequence
;
46 using ::com::sun::star::uno::Reference
;
47 using ::rtl::OUString
;
48 using ::rtl::OUStringBuffer
;
49 using namespace ::com::sun::star
;
54 double lcl_getVariance( const Sequence
< double > & rData
, sal_Int32
& rOutValidCount
,
55 bool bUnbiasedEstimator
)
57 const sal_Int32 nCount
= rData
.getLength();
58 rOutValidCount
= nCount
;
61 double fQuadSum
= 0.0;
63 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
65 const double fData
= rData
[i
];
66 if( ::rtl::math::isNan( fData
))
71 fQuadSum
+= fData
* fData
;
76 if( rOutValidCount
== 0 )
77 ::rtl::math::setNan( & fResult
);
80 const double fN
= static_cast< double >( rOutValidCount
);
81 if( bUnbiasedEstimator
)
82 fResult
= (fQuadSum
- fSum
*fSum
/fN
) / (fN
- 1);
84 fResult
= (fQuadSum
- fSum
*fSum
/fN
) / fN
;
90 Reference
< chart2::data::XLabeledDataSequence
> lcl_getErrorBarLabeledSequence(
91 const Reference
< chart2::data::XDataSource
> & xDataSource
,
92 bool bPositiveValue
, bool bYError
,
93 OUString
& rOutRoleNameUsed
)
95 OUStringBuffer
aRole( C2U("error-bars-"));
97 aRole
.append( sal_Unicode( 'y' ));
99 aRole
.append( sal_Unicode( 'x' ));
101 OUString aPlainRole
= aRole
.makeStringAndClear();
102 aRole
.append( aPlainRole
);
103 aRole
.append( sal_Unicode( '-' ));
106 aRole
= aRole
.appendAscii( "positive" );
108 aRole
= aRole
.appendAscii( "negative" );
110 OUString aLongRole
= aRole
.makeStringAndClear();
111 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
112 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aLongRole
));
113 // try role without "-negative" or "-positive" postfix
115 rOutRoleNameUsed
= aLongRole
;
118 xLSeq
.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aPlainRole
));
120 rOutRoleNameUsed
= aPlainRole
;
122 rOutRoleNameUsed
= aLongRole
;
129 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
130 const OUString
& rRole
)
132 Reference
< beans::XPropertySet
> xSeqProp( xNewSequence
, uno::UNO_QUERY
);
134 xSeqProp
->setPropertyValue( C2U("Role"), uno::makeAny( rRole
));
137 void lcl_addSequenceToDataSource(
138 const Reference
< chart2::data::XDataSource
> & xDataSource
,
139 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
140 const OUString
& rRole
)
142 Reference
< chart2::data::XDataSink
> xSink( xDataSource
, uno::UNO_QUERY
);
143 Reference
< lang::XMultiServiceFactory
> xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
144 if( ! ( xFact
.is() && xSink
.is() ))
147 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
148 xFact
->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY
);
151 lcl_setRole( xNewSequence
, rRole
);
152 xLSeq
->setValues( xNewSequence
);
153 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences(
154 xDataSource
->getDataSequences());
155 aSequences
.realloc( aSequences
.getLength() + 1 );
156 aSequences
[ aSequences
.getLength() - 1 ] = xLSeq
;
157 xSink
->setData( aSequences
);
161 void lcl_setXMLRangePropertyAtDataSequence(
162 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
163 const OUString
& rXMLRange
)
167 const OUString
aXMLRangePropName( C2U( "CachedXMLRange" ));
168 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
169 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
170 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
171 xProp
->setPropertyValue( aXMLRangePropName
, uno::makeAny( rXMLRange
));
173 catch( const uno::Exception
& ex
)
175 ASSERT_EXCEPTION( ex
);
179 } // anonymous namespace
185 double StatisticsHelper::getVariance(
186 const Sequence
< double > & rData
,
187 bool bUnbiasedEstimator
/* = false */ )
190 return lcl_getVariance( rData
, nValCount
, bUnbiasedEstimator
);
194 double StatisticsHelper::getStandardDeviation( const Sequence
< double > & rData
)
196 double fResult
= getVariance( rData
);
197 if( ! ::rtl::math::isNan( fResult
))
198 fResult
= sqrt( fResult
);
204 double StatisticsHelper::getStandardError( const Sequence
< double > & rData
)
207 double fVar
= lcl_getVariance( rData
, nValCount
, false );
210 if( nValCount
== 0 ||
211 ::rtl::math::isNan( fVar
))
213 ::rtl::math::setNan( & fResult
);
217 // standard-deviation / sqrt(n)
218 fResult
= sqrt( fVar
) / sqrt( double(nValCount
) );
225 Reference
< chart2::data::XLabeledDataSequence
> StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
226 const Reference
< chart2::data::XDataSource
> & xDataSource
,
228 bool bYError
/* = true */ )
230 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
231 if( !xDataSource
.is())
235 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
236 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
238 xResult
.set( xLSeq
);
244 Reference
< chart2::data::XDataSequence
> StatisticsHelper::getErrorDataSequenceFromDataSource(
245 const Reference
< chart2::data::XDataSource
> & xDataSource
,
247 bool bYError
/* = true */ )
249 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
250 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
251 xDataSource
, bPositiveValue
,
254 return Reference
< chart2::data::XDataSequence
>();
256 return xLSeq
->getValues();
260 double StatisticsHelper::getErrorFromDataSource(
261 const Reference
< chart2::data::XDataSource
> & xDataSource
,
264 bool bYError
/* = true */ )
266 double fResult
= 0.0;
267 ::rtl::math::setNan( & fResult
);
269 Reference
< chart2::data::XDataSequence
> xValues(
270 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource
, bPositiveValue
, bYError
));
272 Reference
< chart2::data::XNumericalDataSequence
> xNumValues( xValues
, uno::UNO_QUERY
);
275 Sequence
< double > aData( xNumValues
->getNumericalData());
276 if( nIndex
< aData
.getLength())
277 fResult
= aData
[nIndex
];
279 else if( xValues
.is())
281 Sequence
< uno::Any
> aData( xValues
->getData());
282 if( nIndex
< aData
.getLength())
283 aData
[nIndex
] >>= fResult
;
290 void StatisticsHelper::setErrorDataSequence(
291 const Reference
< chart2::data::XDataSource
> & xDataSource
,
292 const Reference
< chart2::data::XDataProvider
> & xDataProvider
,
293 const OUString
& rNewRange
,
295 bool bYError
/* = true */,
296 OUString
* pXMLRange
/* = 0 */ )
298 Reference
< chart2::data::XDataSink
> xDataSink( xDataSource
, uno::UNO_QUERY
);
299 if( ! ( xDataSink
.is() && xDataProvider
.is()))
303 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
304 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
305 Reference
< chart2::data::XDataSequence
> xNewSequence(
306 xDataProvider
->createDataSequenceByRangeRepresentation( rNewRange
));
307 if( xNewSequence
.is())
310 lcl_setXMLRangePropertyAtDataSequence( xNewSequence
, *pXMLRange
);
313 lcl_setRole( xNewSequence
, aRole
);
314 xLSeq
->setValues( xNewSequence
);
317 lcl_addSequenceToDataSource( xDataSource
, xNewSequence
, aRole
);
322 Reference
< beans::XPropertySet
> StatisticsHelper::addErrorBars(
323 const Reference
< chart2::XDataSeries
> & xDataSeries
,
324 const Reference
< uno::XComponentContext
> & xContext
,
326 bool bYError
/* = true */ )
328 Reference
< beans::XPropertySet
> xErrorBar
;
329 Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
330 if( !xSeriesProp
.is())
333 const OUString
aPropName( bYError
? C2U("ErrorBarY") : C2U("ErrorBarX"));
334 if( !( xSeriesProp
->getPropertyValue( aPropName
) >>= xErrorBar
) ||
337 xErrorBar
.set( createErrorBar( xContext
));
340 OSL_ASSERT( xErrorBar
.is());
343 xErrorBar
->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle
));
346 xSeriesProp
->setPropertyValue( aPropName
, uno::makeAny( xErrorBar
));
352 Reference
< beans::XPropertySet
> StatisticsHelper::getErrorBars(
353 const Reference
< chart2::XDataSeries
> & xDataSeries
,
354 bool bYError
/* = true */ )
356 Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
357 Reference
< beans::XPropertySet
> xErrorBar
;
358 const OUString
aPropName( bYError
? C2U("ErrorBarY") : C2U("ErrorBarX"));
360 if ( xSeriesProp
.is())
361 xSeriesProp
->getPropertyValue( aPropName
) >>= xErrorBar
;
367 bool StatisticsHelper::hasErrorBars(
368 const Reference
< chart2::XDataSeries
> & xDataSeries
,
369 bool bYError
/* = true */ )
371 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
372 sal_Int32 nStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
374 return ( xErrorBar
.is() &&
375 ( xErrorBar
->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle
) &&
376 nStyle
!= ::com::sun::star::chart::ErrorBarStyle::NONE
);
380 void StatisticsHelper::removeErrorBars(
381 const Reference
< chart2::XDataSeries
> & xDataSeries
,
382 bool bYError
/* = true */ )
384 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
386 xErrorBar
->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny(
387 ::com::sun::star::chart::ErrorBarStyle::NONE
));
391 bool StatisticsHelper::usesErrorBarRanges(
392 const Reference
< chart2::XDataSeries
> & xDataSeries
,
393 bool bYError
/* = true */ )
395 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
396 sal_Int32 nStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
398 return ( xErrorBar
.is() &&
399 ( xErrorBar
->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle
) &&
400 nStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
);