Skip to content

Commit b8103d8

Browse files
committed
reviewed readme for unitofmeasure functionality
1 parent d47f2b3 commit b8103d8

File tree

1 file changed

+148
-25
lines changed

1 file changed

+148
-25
lines changed

README.md

Lines changed: 148 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,154 @@ To construct a GME Public Offer Extraction the following must be provided.
442442
443443
</table>
444444

445+
### Unit of Measure Conversion Functionality
446+
447+
### Overview
448+
449+
The unit of measure conversion functionality allows users to request a conversion of units for Market Data that was registered using a different unit. This feature is supported only for Actual and Versioned Time Series.
450+
Supported units are defined in the CommonUnitOfMeasure object and conform to ISO/IEC 80000 (i.e., `kW`, `MW`, `kWh`, `MWh`, `m`, `km`, `day`, `min`, `h`, `s`, `mo`, `yr`).
451+
452+
Note: Duration-based units are interpreted with the following fixed assumptions:
453+
`1 day = 24 hours`
454+
`1 mo = 30 days`
455+
`1 yr = 365 days`
456+
457+
Additional supported units include **currency codes** in 3-letter format as per ISO 4217:2015 (e.g., `EUR`, `USD`, `JPY`). These are not part of CommonUnitOfMeasure and must be specified as regular strings.
458+
Units of measure can also be **composite**, using the {a}/{b} syntax, where both {a} and {b} are either units from CommonUnitOfMeasure or ISO 4217 currency codes.
459+
460+
### Conversion Logic
461+
462+
Unit conversion is based on the assumption that each unit of measure can be decomposed into a **"BaseDimension"**, which represents a polynomial of base SI units (`m`, `s`, `kg`, etc.) and currencies (`EUR`, `USD`, etc.).
463+
A unit of measure is represented as a value in BaseDimension UnitOdMeasure.
464+
Example:
465+
10 `Wh` = 10 `kg·m²·s⁻³`
466+
Conversion is allowed when the BaseDimensions **match exactly**, i.e., the same set of base units raised to the same exponents.
467+
In Artesian, units that differ **only** in the **time dimension** are also potentially convertible, as the time dimension can be inferred from the data’s time interval.
468+
469+
### Example: Power to Energy Conversion
470+
471+
Converting `W` to `Wh`:
472+
`W` → BaseDimension: `k·m²·s⁻³`
473+
`Wh` → BaseDimension: `kg·m²·s⁻²`
474+
`1 h = 3600 s`
475+
**Conversion Steps:**
476+
10 W = 10 kg·m²/s³
477+
1 h = 3600 s
478+
10 kg·m²/s³ × 3600 s = 36000 kg·m²/s² = 10 Wh
479+
480+
### MarketData Registration with UnitOfMeasure
481+
482+
The UnitOfMeasure is defined during registration:
483+
484+
```Python
485+
mkd = MarketData.MarketDataEntityInput(
486+
providerName = "TestProviderName",
487+
marketDataName = "TestMarketDataName",
488+
originalGranularity=Granularity.Day,
489+
type=MarketData.MarketDataType.ActualTimeSerie,
490+
originalTimezone="CET",
491+
aggregationRule=AggregationRule.SumAndDivide,
492+
UnitOfMeasure = CommonUnitOfMeasure.kW
493+
)
494+
495+
registered = mkservice.readMarketDataRegistryByName(mkdid.provider, mkdid.name)
496+
if (registered is None):
497+
registered = mkservice.registerMarketData(mkd)
498+
```
499+
500+
### UnitOfMeasure Conversion and Aggregation Rule Override
501+
502+
In the QueryService, there are two supported methods related to unit of measure handling during extraction:
503+
504+
1. UnitOfMeasure Conversion
505+
2. Aggregation Rule Override
506+
507+
### UnitOfMeasure Conversion
508+
509+
To convert a UnitOfMeasure during data extraction, use the `.inUnitOfMeasure()` method. This function converts the data from the unit defined at MarketData registration to the target unit you specify in the query.
510+
511+
```Python
512+
qs = QueryService(cfg)
513+
data = qs.createActual() \
514+
.forMarketData([100011484]) \
515+
.inAbsoluteDateRange("2024-01-01","2024-01-02") \
516+
.inTimeZone("UTC") \
517+
.inGranularity(Granularity.Day) \
518+
.inUnitOfMeasure(CommonUnitOfMeasure.MW) \
519+
.execute()
520+
```
521+
522+
By default, the aggregation rule used during extraction is the one defined at registration. However, you can override it if needed. The conversion is always applied before aggregation.
523+
524+
### Aggregation Rule Override
525+
526+
AggregationRule can be overrided using the `.withAggregationRule()` method in QueryService.
527+
528+
```Python
529+
qs = QueryService(cfg)
530+
data = qs.createActual() \
531+
.forMarketData([100011484]) \
532+
.inAbsoluteDateRange("2024-01-01","2024-01-02") \
533+
.inTimeZone("UTC") \
534+
.inGranularity(Granularity.Day) \
535+
.withAggregationRule(AggregationRule.AverageAndReplicate) \
536+
.execute()
537+
```
538+
539+
Sometimes, especially when converting from a **consumption unit** (e.g., `MWh`) to a **power unit** (e.g., `MW`), the registered aggregation rule (e.g., `SumAndDivide`) may not make sense for the new unit.
540+
541+
If you **don’t override the aggregation rule**, the conversion may produce **invalid or misleading results**.
542+
543+
### Example: Convert power (`MW`) to energy (`MWh`):
544+
545+
```Python
546+
data = qs.createActual() \
547+
.forMarketData([100011484]) \
548+
.inAbsoluteDateRange("2024-01-01","2024-01-02") \
549+
.inTimeZone("UTC") \
550+
.inGranularity(Granularity.Day) \
551+
.inUnitOfMeasure(CommonUnitOfMeasure.MWh) \
552+
.withAggregationRule(AggregationRule.AverageAndReplicate) \
553+
.execute()
554+
```
555+
556+
### Composite Unit Example: `MWh/day`
557+
558+
```Python
559+
data = qs.createActual() \
560+
.forMarketData([100011484]) \
561+
.inAbsoluteDateRange("2024-01-01","2024-01-02") \
562+
.inTimeZone("UTC") \
563+
.inGranularity(Granularity.Day) \
564+
.inUnitOfMeasure(CommonUnitOfMeasure.MWh / CommonUnitOfMeasure.day) \
565+
.withAggregationRule(AggregationRule.AverageAndReplicate) \
566+
.execute()
567+
```
568+
569+
### CheckConversion: Validate Unit Compatibility
570+
571+
Use the `CheckConversion` method to verify whether a list of input units can be converted into a specifified target unit:
572+
573+
```Python
574+
from Artesian import ArtesianConfig, MarketData
575+
from Artesian.MarketData import CommonUnitOfMeasure
576+
577+
cfg = ArtesianConfg()
578+
579+
mkservice = MarketData.MarketDataService(cfg)
580+
581+
inputUnitsOfMeasure = [CommonUnitOfMeasure.kW, CommonUnitOfMeasure.kWh, "EUR/MWh"]
582+
targetUnitOfMeasure = CommonUnitOfMeasure.MW
583+
584+
checkConversionResult = mkservice.checkConversion(inputUnitsOfMeasure , targetUnitOfMeasure)
585+
```
586+
587+
**Returned Object: CheckConversionResult**
588+
589+
1. TargetUnitOfMeasure: "`kW`"
590+
2. ConvertibleInputUnitsOfMeasure: [ "`MW`", "`kW/s`" ]
591+
3. NotConvertibleInputUnitsOfMeasure: [ "`s`" ]
592+
445593
### Extraction Options
446594

447595
Extraction options for GME Public Offer queries.
@@ -957,31 +1105,6 @@ deleteData = MarketData.DeleteData(
9571105
mkdservice.deleteData(deleteData)
9581106
```
9591107

960-
### CheckConversion of UnitOfMeasures
961-
962-
MarketData Service provides a method called CheckConversion, which allows you to check whether a list of input units of measure can be converted info a specified target unit of measure.
963-
964-
```Python
965-
from Artesian import ArtesianConfig, MarketData
966-
from Artesian.MarketData import CommonUnitOfMeasure
967-
968-
cfg = ArtesianConfg()
969-
970-
mkservice = MarketData.MarketDataService(cfg)
971-
972-
inputUnitsOfMeasure = [CommonUnitOfMeasure.kW, CommonUnitOfMeasure.kWh, "EUR/MWh"]
973-
targetUnitOfMeasure = CommonUnitOfMeasure.MW
974-
975-
checkConversionResult = mkservice.checkConversion(inputUnitsOfMeasure , targetUnitOfMeasure)
976-
```
977-
978-
Output:
979-
The method will return a CheckConversionResult object containing the results of the conversion check.
980-
981-
TargetUnitOfMeasure = the unit of measure you're converting to.
982-
ConvertibleInputUnitsOfMeasure = a list of input units that can be successfully converted to the target unit.
983-
NotConvertibleInputUnitsOfMeasure = a list of input units that cannot be converted to the target unit.
984-
9851108
## Jupyter Support
9861109

9871110
Artesian SDK uses asyncio internally, this causes a conflict with Jupyter. You can work around this issue by add the following at the beginning of the notebook.

0 commit comments

Comments
 (0)