1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <StatisticsHelper.hxx>
21 #include <DataSeriesHelper.hxx>
22 #include <ErrorBar.hxx>
23 #include <unonames.hxx>
25 #include <rtl/math.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <comphelper/processfactory.hxx>
29 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
30 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
31 #include <com/sun/star/chart2/data/XDataProvider.hpp>
32 #include <com/sun/star/chart2/data/XDataSink.hpp>
33 #include <com/sun/star/chart/ErrorBarStyle.hpp>
34 #include <tools/diagnose_ex.h>
36 using ::com::sun::star::uno::Sequence
;
37 using ::com::sun::star::uno::Reference
;
38 using namespace ::com::sun::star
;
43 double lcl_getVariance( const Sequence
< double > & rData
, sal_Int32
& rOutValidCount
)
45 const sal_Int32 nCount
= rData
.getLength();
46 rOutValidCount
= nCount
;
49 double fQuadSum
= 0.0;
51 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
53 const double fData
= rData
[i
];
54 if( ::rtl::math::isNan( fData
))
59 fQuadSum
+= fData
* fData
;
64 if( rOutValidCount
== 0 )
65 ::rtl::math::setNan( & fResult
);
68 const double fN
= static_cast< double >( rOutValidCount
);
69 fResult
= (fQuadSum
- fSum
*fSum
/fN
) / fN
;
75 Reference
< chart2::data::XLabeledDataSequence
> lcl_getErrorBarLabeledSequence(
76 const Reference
< chart2::data::XDataSource
> & xDataSource
,
77 bool bPositiveValue
, bool bYError
,
78 OUString
& rOutRoleNameUsed
)
80 OUStringBuffer
aRole( "error-bars-");
86 OUString aPlainRole
= aRole
.makeStringAndClear();
87 aRole
.append( aPlainRole
);
91 aRole
.append( "positive" );
93 aRole
.append( "negative" );
95 OUString aLongRole
= aRole
.makeStringAndClear();
96 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
97 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aLongRole
));
98 // try role without "-negative" or "-positive" postfix
100 rOutRoleNameUsed
= aLongRole
;
103 xLSeq
.set( ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aPlainRole
));
105 rOutRoleNameUsed
= aPlainRole
;
107 rOutRoleNameUsed
= aLongRole
;
114 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
115 const OUString
& rRole
)
117 Reference
< beans::XPropertySet
> xSeqProp( xNewSequence
, uno::UNO_QUERY
);
119 xSeqProp
->setPropertyValue( "Role", uno::Any( rRole
));
122 void lcl_addSequenceToDataSource(
123 const Reference
< chart2::data::XDataSource
> & xDataSource
,
124 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
125 const OUString
& rRole
)
127 Reference
< chart2::data::XDataSink
> xSink( xDataSource
, uno::UNO_QUERY
);
128 Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
132 Reference
< chart2::data::XLabeledDataSequence
> xLSeq( chart2::data::LabeledDataSequence::create(xContext
), uno::UNO_QUERY_THROW
);
134 lcl_setRole( xNewSequence
, rRole
);
135 xLSeq
->setValues( xNewSequence
);
136 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences(
137 xDataSource
->getDataSequences());
138 aSequences
.realloc( aSequences
.getLength() + 1 );
139 aSequences
[ aSequences
.getLength() - 1 ] = xLSeq
;
140 xSink
->setData( aSequences
);
143 void lcl_setXMLRangePropertyAtDataSequence(
144 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
145 const OUString
& rXMLRange
)
149 const OUString
aXMLRangePropName( "CachedXMLRange");
150 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
151 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
152 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
153 xProp
->setPropertyValue( aXMLRangePropName
, uno::Any( rXMLRange
));
155 catch( const uno::Exception
& )
157 DBG_UNHANDLED_EXCEPTION("chart2");
161 } // anonymous namespace
166 double StatisticsHelper::getVariance(
167 const Sequence
< double > & rData
)
170 return lcl_getVariance( rData
, nValCount
);
173 double StatisticsHelper::getStandardDeviation( const Sequence
< double > & rData
)
175 double fResult
= getVariance( rData
);
176 if( ! ::rtl::math::isNan( fResult
))
177 fResult
= sqrt( fResult
);
182 double StatisticsHelper::getStandardError( const Sequence
< double > & rData
)
185 double fVar
= lcl_getVariance( rData
, nValCount
);
188 if( nValCount
== 0 ||
189 ::rtl::math::isNan( fVar
))
191 ::rtl::math::setNan( & fResult
);
195 // standard-deviation / sqrt(n)
196 fResult
= sqrt( fVar
) / sqrt( double(nValCount
) );
202 Reference
< chart2::data::XLabeledDataSequence
> StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
203 const Reference
< chart2::data::XDataSource
> & xDataSource
,
205 bool bYError
/* = true */ )
207 Reference
< chart2::data::XLabeledDataSequence
> xResult
;
208 if( !xDataSource
.is())
212 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
213 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
215 xResult
.set( xLSeq
);
220 Reference
< chart2::data::XDataSequence
> StatisticsHelper::getErrorDataSequenceFromDataSource(
221 const Reference
< chart2::data::XDataSource
> & xDataSource
,
223 bool bYError
/* = true */ )
225 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
226 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
227 xDataSource
, bPositiveValue
,
230 return Reference
< chart2::data::XDataSequence
>();
232 return xLSeq
->getValues();
235 double StatisticsHelper::getErrorFromDataSource(
236 const Reference
< chart2::data::XDataSource
> & xDataSource
,
239 bool bYError
/* = true */ )
241 double fResult
= 0.0;
242 ::rtl::math::setNan( & fResult
);
244 Reference
< chart2::data::XDataSequence
> xValues(
245 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource
, bPositiveValue
, bYError
));
247 Reference
< chart2::data::XNumericalDataSequence
> xNumValues( xValues
, uno::UNO_QUERY
);
250 Sequence
< double > aData( xNumValues
->getNumericalData());
251 if( nIndex
< aData
.getLength())
252 fResult
= aData
[nIndex
];
254 else if( xValues
.is())
256 Sequence
< uno::Any
> aData( xValues
->getData());
257 if( nIndex
< aData
.getLength())
258 aData
[nIndex
] >>= fResult
;
264 void StatisticsHelper::setErrorDataSequence(
265 const Reference
< chart2::data::XDataSource
> & xDataSource
,
266 const Reference
< chart2::data::XDataProvider
> & xDataProvider
,
267 const OUString
& rNewRange
,
269 bool bYError
/* = true */,
270 OUString
const * pXMLRange
/* = 0 */ )
272 Reference
< chart2::data::XDataSink
> xDataSink( xDataSource
, uno::UNO_QUERY
);
273 if( ! ( xDataSink
.is() && xDataProvider
.is()))
277 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
278 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
279 Reference
< chart2::data::XDataSequence
> xNewSequence(
280 xDataProvider
->createDataSequenceByRangeRepresentation( rNewRange
));
281 if( xNewSequence
.is())
284 lcl_setXMLRangePropertyAtDataSequence( xNewSequence
, *pXMLRange
);
287 lcl_setRole( xNewSequence
, aRole
);
288 xLSeq
->setValues( xNewSequence
);
291 lcl_addSequenceToDataSource( xDataSource
, xNewSequence
, aRole
);
295 Reference
< beans::XPropertySet
> StatisticsHelper::addErrorBars(
296 const Reference
< chart2::XDataSeries
> & xDataSeries
,
298 bool bYError
/* = true */ )
300 Reference
< beans::XPropertySet
> xErrorBar
;
301 Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
302 if( !xSeriesProp
.is())
305 const OUString
aPropName(
306 bYError
? OUString(CHART_UNONAME_ERRORBAR_Y
) : OUString(CHART_UNONAME_ERRORBAR_X
));
307 if( !( xSeriesProp
->getPropertyValue( aPropName
) >>= xErrorBar
) ||
310 xErrorBar
.set( new ErrorBar
);
313 OSL_ASSERT( xErrorBar
.is());
316 xErrorBar
->setPropertyValue( "ErrorBarStyle", uno::Any( nStyle
));
319 xSeriesProp
->setPropertyValue( aPropName
, uno::Any( xErrorBar
));
324 Reference
< beans::XPropertySet
> StatisticsHelper::getErrorBars(
325 const Reference
< chart2::XDataSeries
> & xDataSeries
,
326 bool bYError
/* = true */ )
328 Reference
< beans::XPropertySet
> xSeriesProp( xDataSeries
, uno::UNO_QUERY
);
329 Reference
< beans::XPropertySet
> xErrorBar
;
330 const OUString
aPropName(
331 bYError
? OUString(CHART_UNONAME_ERRORBAR_Y
) : OUString(CHART_UNONAME_ERRORBAR_X
));
333 if ( xSeriesProp
.is())
334 xSeriesProp
->getPropertyValue( aPropName
) >>= xErrorBar
;
339 bool StatisticsHelper::hasErrorBars(
340 const Reference
< chart2::XDataSeries
> & xDataSeries
,
341 bool bYError
/* = true */ )
343 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
344 sal_Int32 nStyle
= css::chart::ErrorBarStyle::NONE
;
346 return ( xErrorBar
.is() &&
347 ( xErrorBar
->getPropertyValue( "ErrorBarStyle") >>= nStyle
) &&
348 nStyle
!= css::chart::ErrorBarStyle::NONE
);
351 void StatisticsHelper::removeErrorBars(
352 const Reference
< chart2::XDataSeries
> & xDataSeries
,
353 bool bYError
/* = true */ )
355 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
357 xErrorBar
->setPropertyValue( "ErrorBarStyle", uno::Any(
358 css::chart::ErrorBarStyle::NONE
));
361 bool StatisticsHelper::usesErrorBarRanges(
362 const Reference
< chart2::XDataSeries
> & xDataSeries
,
363 bool bYError
/* = true */ )
365 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
366 sal_Int32 nStyle
= css::chart::ErrorBarStyle::NONE
;
368 return ( xErrorBar
.is() &&
369 ( xErrorBar
->getPropertyValue( "ErrorBarStyle") >>= nStyle
) &&
370 nStyle
== css::chart::ErrorBarStyle::FROM_DATA
);
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */