1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: StatisticsHelper.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
33 #include "StatisticsHelper.hxx"
34 #include "DataSeriesHelper.hxx"
35 #include "ErrorBar.hxx"
38 #include <rtl/math.hxx>
39 #include <rtl/ustrbuf.hxx>
40 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
44 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
45 #include <com/sun/star/chart2/data/XDataSink.hpp>
46 #include <com/sun/star/chart/ErrorBarStyle.hpp>
48 using ::com::sun::star::uno::Sequence
;
49 using ::com::sun::star::uno::Reference
;
50 using ::rtl::OUString
;
51 using ::rtl::OUStringBuffer
;
52 using namespace ::com::sun::star
;
57 double lcl_getVariance( const Sequence
< double > & rData
, sal_Int32
& rOutValidCount
,
58 bool bUnbiasedEstimator
)
60 const sal_Int32 nCount
= rData
.getLength();
61 rOutValidCount
= nCount
;
64 double fQuadSum
= 0.0;
66 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
68 const double fData
= rData
[i
];
69 if( ::rtl::math::isNan( fData
))
74 fQuadSum
+= fData
* fData
;
79 if( rOutValidCount
== 0 )
80 ::rtl::math::setNan( & fResult
);
83 const double fN
= static_cast< double >( rOutValidCount
);
84 if( bUnbiasedEstimator
)
85 fResult
= (fQuadSum
- fSum
*fSum
/fN
) / (fN
- 1);
87 fResult
= (fQuadSum
- fSum
*fSum
/fN
) / fN
;
93 Reference
< chart2::data::XLabeledDataSequence
> lcl_getErrorBarLabeledSequence(
94 const Reference
< chart2::data::XDataSource
> & xDataSource
,
95 bool bPositiveValue
, bool bYError
,
96 OUString
& rOutRoleNameUsed
)
98 OUStringBuffer
aRole( C2U("error-bars-"));
100 aRole
.append( sal_Unicode( 'y' ));
102 aRole
.append( sal_Unicode( 'x' ));
104 OUString aPlainRole
= aRole
.makeStringAndClear();
105 aRole
.append( aPlainRole
);
106 aRole
.append( sal_Unicode( '-' ));
109 aRole
= aRole
.appendAscii( "positive" );
111 aRole
= aRole
.appendAscii( "negative" );
113 OUString aLongRole
= aRole
.makeStringAndClear();
114 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
115 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aLongRole
));
116 // try role without "-negative" or "-positive" postfix
118 rOutRoleNameUsed
= aLongRole
;
121 xLSeq
.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aPlainRole
));
123 rOutRoleNameUsed
= aPlainRole
;
125 rOutRoleNameUsed
= aLongRole
;
132 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
133 const OUString
& rRole
)
135 Reference
< beans::XPropertySet
> xSeqProp( xNewSequence
, uno::UNO_QUERY
);
137 xSeqProp
->setPropertyValue( C2U("Role"), uno::makeAny( rRole
));
140 void lcl_addSequenceToDataSource(
141 const Reference
< chart2::data::XDataSource
> & xDataSource
,
142 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
143 const OUString
& rRole
)
145 Reference
< chart2::data::XDataSink
> xSink( xDataSource
, uno::UNO_QUERY
);
146 Reference
< lang::XMultiServiceFactory
> xFact( comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW
);
147 if( ! ( xFact
.is() && xSink
.is() ))
150 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
151 xFact
->createInstance( C2U("com.sun.star.chart2.data.LabeledDataSequence")), uno::UNO_QUERY
);
154 lcl_setRole( xNewSequence
, rRole
);
155 xLSeq
->setValues( xNewSequence
);
156 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences(
157 xDataSource
->getDataSequences());
158 aSequences
.realloc( aSequences
.getLength() + 1 );
159 aSequences
[ aSequences
.getLength() - 1 ] = xLSeq
;
160 xSink
->setData( aSequences
);
164 void lcl_setXMLRangePropertyAtDataSequence(
165 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
166 const OUString
& rXMLRange
)
170 const OUString
aXMLRangePropName( C2U( "CachedXMLRange" ));
171 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
172 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
173 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
174 xProp
->setPropertyValue( aXMLRangePropName
, uno::makeAny( rXMLRange
));
176 catch( const uno::Exception
& ex
)
178 ASSERT_EXCEPTION( ex
);
182 } // anonymous namespace
188 double StatisticsHelper::getVariance(
189 const Sequence
< double > & rData
,
190 bool bUnbiasedEstimator
/* = false */ )
193 return lcl_getVariance( rData
, nValCount
, bUnbiasedEstimator
);
197 double StatisticsHelper::getStandardDeviation( const Sequence
< double > & rData
)
199 double fResult
= getVariance( rData
);
200 if( ! ::rtl::math::isNan( fResult
))
201 fResult
= sqrt( fResult
);
207 double StatisticsHelper::getStandardError( const Sequence
< double > & rData
)
210 double fVar
= lcl_getVariance( rData
, nValCount
, false );
213 if( nValCount
== 0 ||
214 ::rtl::math::isNan( fVar
))
216 ::rtl::math::setNan( & fResult
);
220 // standard-deviation / sqrt(n)
221 fResult
= sqrt( fVar
) / sqrt( double(nValCount
) );
228 Reference
< chart2::data::XLabeledDataSequence
> StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
229 const Reference
< chart2::data::XDataSource
> & xDataSource
,
231 bool bYError
/* = true */ )
233 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
234 if( !xDataSource
.is())
238 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
239 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
241 xResult
.set( xLSeq
);
247 Reference
< chart2::data::XDataSequence
> StatisticsHelper::getErrorDataSequenceFromDataSource(
248 const Reference
< chart2::data::XDataSource
> & xDataSource
,
250 bool bYError
/* = true */ )
252 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
253 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
254 xDataSource
, bPositiveValue
,
257 return Reference
< chart2::data::XDataSequence
>();
259 return xLSeq
->getValues();
263 double StatisticsHelper::getErrorFromDataSource(
264 const Reference
< chart2::data::XDataSource
> & xDataSource
,
267 bool bYError
/* = true */ )
269 double fResult
= 0.0;
270 ::rtl::math::setNan( & fResult
);
272 Reference
< chart2::data::XDataSequence
> xValues(
273 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource
, bPositiveValue
, bYError
));
275 Reference
< chart2::data::XNumericalDataSequence
> xNumValues( xValues
, uno::UNO_QUERY
);
278 Sequence
< double > aData( xNumValues
->getNumericalData());
279 if( nIndex
< aData
.getLength())
280 fResult
= aData
[nIndex
];
282 else if( xValues
.is())
284 Sequence
< uno::Any
> aData( xValues
->getData());
285 if( nIndex
< aData
.getLength())
286 aData
[nIndex
] >>= fResult
;
293 void StatisticsHelper::setErrorDataSequence(
294 const Reference
< chart2::data::XDataSource
> & xDataSource
,
295 const Reference
< chart2::data::XDataProvider
> & xDataProvider
,
296 const OUString
& rNewRange
,
298 bool bYError
/* = true */,
299 OUString
* pXMLRange
/* = 0 */ )
301 Reference
< chart2::data::XDataSink
> xDataSink( xDataSource
, uno::UNO_QUERY
);
302 if( ! ( xDataSink
.is() && xDataProvider
.is()))
306 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
307 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
308 Reference
< chart2::data::XDataSequence
> xNewSequence(
309 xDataProvider
->createDataSequenceByRangeRepresentation( rNewRange
));
310 if( xNewSequence
.is())
313 lcl_setXMLRangePropertyAtDataSequence( xNewSequence
, *pXMLRange
);
316 lcl_setRole( xNewSequence
, aRole
);
317 xLSeq
->setValues( xNewSequence
);
320 lcl_addSequenceToDataSource( xDataSource
, xNewSequence
, aRole
);
325 Reference
< beans::XPropertySet
> StatisticsHelper::addErrorBars(
326 const Reference
< chart2::XDataSeries
> & xDataSeries
,
327 const Reference
< uno::XComponentContext
> & xContext
,
329 bool bYError
/* = true */ )
331 Reference
< beans::XPropertySet
> xErrorBar
;
332 Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
333 if( !xSeriesProp
.is())
336 const OUString
aPropName( bYError
? C2U("ErrorBarY") : C2U("ErrorBarX"));
337 if( !( xSeriesProp
->getPropertyValue( aPropName
) >>= xErrorBar
) ||
340 xErrorBar
.set( createErrorBar( xContext
));
343 OSL_ASSERT( xErrorBar
.is());
346 xErrorBar
->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny( nStyle
));
349 xSeriesProp
->setPropertyValue( aPropName
, uno::makeAny( xErrorBar
));
355 Reference
< beans::XPropertySet
> StatisticsHelper::getErrorBars(
356 const Reference
< chart2::XDataSeries
> & xDataSeries
,
357 bool bYError
/* = true */ )
359 Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
360 Reference
< beans::XPropertySet
> xErrorBar
;
361 const OUString
aPropName( bYError
? C2U("ErrorBarY") : C2U("ErrorBarX"));
363 if ( xSeriesProp
.is())
364 xSeriesProp
->getPropertyValue( aPropName
) >>= xErrorBar
;
370 bool StatisticsHelper::hasErrorBars(
371 const Reference
< chart2::XDataSeries
> & xDataSeries
,
372 bool bYError
/* = true */ )
374 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
375 sal_Int32 nStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
377 return ( xErrorBar
.is() &&
378 ( xErrorBar
->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle
) &&
379 nStyle
!= ::com::sun::star::chart::ErrorBarStyle::NONE
);
383 void StatisticsHelper::removeErrorBars(
384 const Reference
< chart2::XDataSeries
> & xDataSeries
,
385 bool bYError
/* = true */ )
387 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
389 xErrorBar
->setPropertyValue( C2U("ErrorBarStyle"), uno::makeAny(
390 ::com::sun::star::chart::ErrorBarStyle::NONE
));
394 bool StatisticsHelper::usesErrorBarRanges(
395 const Reference
< chart2::XDataSeries
> & xDataSeries
,
396 bool bYError
/* = true */ )
398 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
399 sal_Int32 nStyle
= ::com::sun::star::chart::ErrorBarStyle::NONE
;
401 return ( xErrorBar
.is() &&
402 ( xErrorBar
->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle
) &&
403 nStyle
== ::com::sun::star::chart::ErrorBarStyle::FROM_DATA
);