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 <DataSeries.hxx>
22 #include <DataSeriesHelper.hxx>
23 #include <ErrorBar.hxx>
24 #include <unonames.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <comphelper/processfactory.hxx>
28 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
29 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
30 #include <com/sun/star/chart2/data/XDataProvider.hpp>
31 #include <com/sun/star/chart2/data/XDataSink.hpp>
32 #include <com/sun/star/chart/ErrorBarStyle.hpp>
33 #include <comphelper/diagnose_ex.hxx>
38 using ::com::sun::star::uno::Sequence
;
39 using ::com::sun::star::uno::Reference
;
40 using namespace ::com::sun::star
;
45 double lcl_getVariance( const Sequence
< double > & rData
, sal_Int32
& rOutValidCount
)
47 const sal_Int32 nCount
= rData
.getLength();
48 rOutValidCount
= nCount
;
51 double fQuadSum
= 0.0;
53 for( sal_Int32 i
= 0; i
< nCount
; ++i
)
55 const double fData
= rData
[i
];
56 if( std::isnan( fData
))
61 fQuadSum
+= fData
* fData
;
65 if( rOutValidCount
== 0 )
66 return std::numeric_limits
<double>::quiet_NaN();
68 const double fN
= static_cast< double >( rOutValidCount
);
69 return (fQuadSum
- fSum
*fSum
/fN
) / fN
;
72 uno::Reference
< chart2::data::XLabeledDataSequence
> lcl_getErrorBarLabeledSequence(
73 const Reference
< chart2::data::XDataSource
> & xDataSource
,
74 bool bPositiveValue
, bool bYError
,
75 OUString
& rOutRoleNameUsed
)
77 OUStringBuffer
aRole( "error-bars-");
83 OUString aPlainRole
= aRole
.makeStringAndClear();
84 aRole
.append( aPlainRole
+ "-" );
87 aRole
.append( "positive" );
89 aRole
.append( "negative" );
91 OUString aLongRole
= aRole
.makeStringAndClear();
92 uno::Reference
< chart2::data::XLabeledDataSequence
> xLSeq
=
93 ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aLongRole
);
94 // try role without "-negative" or "-positive" postfix
96 rOutRoleNameUsed
= aLongRole
;
99 xLSeq
= ::chart::DataSeriesHelper::getDataSequenceByRole( xDataSource
, aPlainRole
);
101 rOutRoleNameUsed
= aPlainRole
;
103 rOutRoleNameUsed
= aLongRole
;
110 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
111 const OUString
& rRole
)
113 Reference
< beans::XPropertySet
> xSeqProp( xNewSequence
, uno::UNO_QUERY
);
115 xSeqProp
->setPropertyValue( u
"Role"_ustr
, uno::Any( rRole
));
118 void lcl_addSequenceToDataSource(
119 const Reference
< chart2::data::XDataSource
> & xDataSource
,
120 const Reference
< chart2::data::XDataSequence
> & xNewSequence
,
121 const OUString
& rRole
)
123 Reference
< chart2::data::XDataSink
> xSink( xDataSource
, uno::UNO_QUERY
);
124 const Reference
< uno::XComponentContext
>& xContext( comphelper::getProcessComponentContext() );
128 Reference
< chart2::data::XLabeledDataSequence
> xLSeq( chart2::data::LabeledDataSequence::create(xContext
), uno::UNO_QUERY_THROW
);
130 lcl_setRole( xNewSequence
, rRole
);
131 xLSeq
->setValues( xNewSequence
);
132 Sequence
< Reference
< chart2::data::XLabeledDataSequence
> > aSequences(
133 xDataSource
->getDataSequences());
134 aSequences
.realloc( aSequences
.getLength() + 1 );
135 auto pSequences
= aSequences
.getArray();
136 pSequences
[ aSequences
.getLength() - 1 ] = std::move(xLSeq
);
137 xSink
->setData( aSequences
);
140 void lcl_setXMLRangePropertyAtDataSequence(
141 const Reference
< chart2::data::XDataSequence
> & xDataSequence
,
142 const OUString
& rXMLRange
)
146 static constexpr OUString
aXMLRangePropName( u
"CachedXMLRange"_ustr
);
147 Reference
< beans::XPropertySet
> xProp( xDataSequence
, uno::UNO_QUERY_THROW
);
148 Reference
< beans::XPropertySetInfo
> xInfo( xProp
->getPropertySetInfo());
149 if( xInfo
.is() && xInfo
->hasPropertyByName( aXMLRangePropName
))
150 xProp
->setPropertyValue( aXMLRangePropName
, uno::Any( rXMLRange
));
152 catch( const uno::Exception
& )
154 DBG_UNHANDLED_EXCEPTION("chart2");
158 } // anonymous namespace
163 double StatisticsHelper::getVariance(
164 const Sequence
< double > & rData
)
167 return lcl_getVariance( rData
, nValCount
);
170 double StatisticsHelper::getStandardDeviation( const Sequence
< double > & rData
)
172 double fResult
= getVariance( rData
);
173 if( ! std::isnan( fResult
))
174 fResult
= sqrt( fResult
);
179 double StatisticsHelper::getStandardError( const Sequence
< double > & rData
)
182 double fVar
= lcl_getVariance( rData
, nValCount
);
184 if( nValCount
== 0 || std::isnan( fVar
))
185 return std::numeric_limits
<double>::quiet_NaN();
186 // standard-deviation / sqrt(n)
187 return sqrt( fVar
) / sqrt( double(nValCount
) );
190 uno::Reference
< chart2::data::XLabeledDataSequence
> StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
191 const Reference
< chart2::data::XDataSource
> & xDataSource
,
193 bool bYError
/* = true */ )
195 uno::Reference
< chart2::data::XLabeledDataSequence
> xResult
;
196 if( !xDataSource
.is())
200 uno::Reference
< chart2::data::XLabeledDataSequence
> xLSeq
=
201 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
);
203 xResult
= std::move(xLSeq
);
208 Reference
< chart2::data::XDataSequence
> StatisticsHelper::getErrorDataSequenceFromDataSource(
209 const Reference
< chart2::data::XDataSource
> & xDataSource
,
211 bool bYError
/* = true */ )
213 uno::Reference
< chart2::data::XLabeledDataSequence
> xLSeq
=
214 StatisticsHelper::getErrorLabeledDataSequenceFromDataSource(
215 xDataSource
, bPositiveValue
,
218 return Reference
< chart2::data::XDataSequence
>();
220 return xLSeq
->getValues();
223 double StatisticsHelper::getErrorFromDataSource(
224 const Reference
< chart2::data::XDataSource
> & xDataSource
,
227 bool bYError
/* = true */ )
229 double fResult
= std::numeric_limits
<double>::quiet_NaN();
231 Reference
< chart2::data::XDataSequence
> xValues(
232 StatisticsHelper::getErrorDataSequenceFromDataSource( xDataSource
, bPositiveValue
, bYError
));
234 Reference
< chart2::data::XNumericalDataSequence
> xNumValues( xValues
, uno::UNO_QUERY
);
237 Sequence
< double > aData( xNumValues
->getNumericalData());
238 if( nIndex
< aData
.getLength())
239 fResult
= aData
[nIndex
];
241 else if( xValues
.is())
243 Sequence
< uno::Any
> aData( xValues
->getData());
244 if( nIndex
< aData
.getLength())
245 aData
[nIndex
] >>= fResult
;
251 void StatisticsHelper::setErrorDataSequence(
252 const Reference
< chart2::data::XDataSource
> & xDataSource
,
253 const Reference
< chart2::data::XDataProvider
> & xDataProvider
,
254 const OUString
& rNewRange
,
256 bool bYError
/* = true */,
257 OUString
const * pXMLRange
/* = 0 */ )
259 Reference
< chart2::data::XDataSink
> xDataSink( xDataSource
, uno::UNO_QUERY
);
260 if( ! ( xDataSink
.is() && xDataProvider
.is()))
264 Reference
< chart2::data::XLabeledDataSequence
> xLSeq(
265 lcl_getErrorBarLabeledSequence( xDataSource
, bPositiveValue
, bYError
, aRole
));
266 Reference
< chart2::data::XDataSequence
> xNewSequence(
267 xDataProvider
->createDataSequenceByRangeRepresentation( rNewRange
));
268 if( xNewSequence
.is())
271 lcl_setXMLRangePropertyAtDataSequence( xNewSequence
, *pXMLRange
);
274 lcl_setRole( xNewSequence
, aRole
);
275 xLSeq
->setValues( xNewSequence
);
278 lcl_addSequenceToDataSource( xDataSource
, xNewSequence
, aRole
);
282 Reference
< beans::XPropertySet
> StatisticsHelper::addErrorBars(
283 const rtl::Reference
< DataSeries
> & xDataSeries
,
285 bool bYError
/* = true */ )
287 Reference
< beans::XPropertySet
> xErrorBar
;
288 if( !xDataSeries
.is())
291 const OUString
aPropName(
292 bYError
? CHART_UNONAME_ERRORBAR_Y
: CHART_UNONAME_ERRORBAR_X
);
293 if( !( xDataSeries
->getPropertyValue( aPropName
) >>= xErrorBar
) ||
296 xErrorBar
.set( new ErrorBar
);
299 OSL_ASSERT( xErrorBar
.is());
302 xErrorBar
->setPropertyValue( u
"ErrorBarStyle"_ustr
, uno::Any( nStyle
));
305 xDataSeries
->setPropertyValue( aPropName
, uno::Any( xErrorBar
));
310 Reference
< beans::XPropertySet
> StatisticsHelper::getErrorBars(
311 const rtl::Reference
< DataSeries
> & xDataSeries
,
312 bool bYError
/* = true */ )
314 Reference
< beans::XPropertySet
> xErrorBar
;
315 const OUString
aPropName(
316 bYError
? CHART_UNONAME_ERRORBAR_Y
: CHART_UNONAME_ERRORBAR_X
);
318 if ( xDataSeries
.is())
319 xDataSeries
->getPropertyValue( aPropName
) >>= xErrorBar
;
324 bool StatisticsHelper::hasErrorBars(
325 const rtl::Reference
< DataSeries
> & xDataSeries
,
326 bool bYError
/* = true */ )
328 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
329 sal_Int32 nStyle
= css::chart::ErrorBarStyle::NONE
;
331 return ( xErrorBar
.is() &&
332 ( xErrorBar
->getPropertyValue( u
"ErrorBarStyle"_ustr
) >>= nStyle
) &&
333 nStyle
!= css::chart::ErrorBarStyle::NONE
);
336 void StatisticsHelper::removeErrorBars(
337 const rtl::Reference
< DataSeries
> & xDataSeries
,
338 bool bYError
/* = true */ )
340 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
342 xErrorBar
->setPropertyValue( u
"ErrorBarStyle"_ustr
, uno::Any(
343 css::chart::ErrorBarStyle::NONE
));
346 bool StatisticsHelper::usesErrorBarRanges(
347 const rtl::Reference
< DataSeries
> & xDataSeries
,
348 bool bYError
/* = true */ )
350 Reference
< beans::XPropertySet
> xErrorBar( getErrorBars( xDataSeries
, bYError
));
351 sal_Int32 nStyle
= css::chart::ErrorBarStyle::NONE
;
353 return ( xErrorBar
.is() &&
354 ( xErrorBar
->getPropertyValue( u
"ErrorBarStyle"_ustr
) >>= nStyle
) &&
355 nStyle
== css::chart::ErrorBarStyle::FROM_DATA
);
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */