The FMU results data model
This section describes the data model used for FMU results when exporting with fmu-dataio. For the time being, the data model is hosted as part of fmu-datio.
The data model described herein is new and shiny, and experimental in many aspects. Any feedback on this is greatly appreciated. The most effective feedback is to apply the data model, then use the resulting metadata.
The FMU data model is described using a JSON Schema which contains rules and definitions for all attributes in the data model. This means, in practice, that outgoing metadata from FMU needs to comply with the schema. If data is uploaded to e.g. Sumo, validation will be done on the incoming data to ensure consistency.
About the data model
Why is it made?
FMU is a mighty system developed by and for the subsurface community in Equinor, to make reservoir modeling more efficient, less error-prone and more repeatable with higher quality, mainly through automation of cross-disciplinary workflows. It combines off-the-shelf software with in-house components such as the ERT orchestrator.
FMU is defined more and more by the data it produces, and direct and indirect dependencies on output from FMU is increasing. When FMU results started to be regularly transferred to cloud storage for direct consumption from 2017/2018 and outwards, the need for stable metadata on outgoing data became immiment. Local development on Johan Sverdrup was initiated to cater for the digital ecosystem evolving in and around that particular project, and the need for generalizing became apparent with the development of Sumo, Webviz and other initiatives.
The purpose of the data model is to cater for the existing dependencies, as well as enable more direct usage of FMU results in different contexts. The secondary objective of this data model is to create a normalization layer between the components that create data and the components that use those data. The data model is designed to also be adapted to other sources of data than FMU.
Scope of this data model
This data model covers data produced by FMU workflows. This includes data generated by direct runs of model templates, data produced by pre-processing workflows, data produced in individual realizations or hooked workflows, and data produced by post-processing workflows.
Note
An example of a pre-processing workflow is a set of jobs modifying selected input data for later use in the FMU workflows and/or for comparison with other results in a QC context.
Note
An example of a post-processing workflow is a script that aggregates results across many realizations and/or iterations of an FMU case.
This data model covers data that, in the FMU context, can be linked to a specific case.
Note that e.g. ERT and other components will, and should, have their own data models to cater for their needs. It is not the intention of this data model to cover all aspects of data in the FMU context. The scope is primarily data going out of FMU to be used elsewhere.
A denormalized data model
The data model used for FMU results is a denormalized data model, at least to a certain point. This means that the static data will be repeated many times. Example: Each exported data object contains basic information about the FMU case it belongs to, such as a unique ID for this case, its name, the user that made it, which model template was used, etc. This information if stored in every exported .yml file. This may seem counterintuitive, and differs from a relational database (where this information would typically be stored once, and referred to when needed).
There are a few reasons for choosing a denormalized data model:
First, the components for creating a relational database containing these data is not and would be extremely difficult to implement fast. Also, the nature of data in an FMU context is very distributed, with lots of files spread across many files and folders (currently).
Second, a denormalized data model enables us to utilize search engine technologies for for indexing. This is not efficient for a normalized data model. The penalty for duplicating metadata across many individual files is returned in speed and ease-of-use.
Note
The data model is only denormalized to a certain point. Most likely, it is better described as a hybrid. Example: The concept of a case is used in FMU context. In the outgoing metadata for FMU results, some information about the current case is included. However, details about the case is out of scope. For this, a consumer would have to refer to the owner of the case definition. In FMU contexts, this will be the workflow manager (ERT).
Standardized vs anarchy
Creating a data model for FMU results brings with it some standard. In essence, this represents the next evolution of the existing FMU standard. We haven’t called it “FMU standard 2.0” because although this would ressonate with many people, many would find it revolting. But, sure, if you are so inclined you are allowed to think of it this way. The FMU standard 1.0 is centric around folder structure and file names - a pre-requisite for standardizing for the good old days when files where files, folders were folders, and data could be consumed by double-clicking. Or, by traversing the mounted file system.
With the transition to a cloud-native state comes numerous opportunities - but also great responsibilities. Some of them are visible in the data model, and the data model is in itself a testament to the most important of them: We need to get our data straight.
There are many challenges. Aligning with everyone and everything is one. We probably don’t succeed with that in the first iteration(s). Materializing metadata effectively, and without hassle, during FMU runs (meaning that everything must be fully automated is another. This is what fmu-dataio solves. But, finding the balance between retaining flexibility and enforcing a standard is perhaps the most tricky of all.
This data model has been designed with the great flexibility of FMU in mind. If you are a geologist on an asset using FMU for something important, you need to be able to export any data from your workflow and use that data without having to wait for someone else to rebuild something. For FMU, one glove certainly does not fit all, and this has been taken into account. While the data model and the associated validation will set some requirements that you need to follow, you are still free to do more or less what you want.
We do, however, STRONGLY ENCOURAGE you to not invent too many private wheels. The risk is that your data cannot be used by others.
The materialized metadata has a nested structure which can be represented by Python dictionaries, yaml or json formats. The root level only contains key attributes, where most are nested sub-dictionaries.
Relations to other data models
The data model for FMU results is designed with generalization in mind. While in practice this data model cover data produced by, or in direct relations to, an FMU workflow - in theory it relates more to subsurface predictive modeling generally, than FMU specifically.
In Equinor, FMU is the primary system for creating, maintaining and using 3D predictive numerical models for the subsurface. Therefore, FMU is the main use case for this data model.
There are plenty of other data models in play in the complex world of subsurface predictive modeling. Each software applies its own data model, and in FMU this encompasses multiple different systems.
Similarly, there are other data models in the larger scope where FMU workflows represent one out of many providors/consumers of data. A significant motivation for defining this data model is to ensure consistency towards other systems and enable stable conditions for integration.
fmu-dataio has three important roles in this context:
Be a translating layer between individual softwares’ data models and the FMU results data model.
Enable fully-automated materialization of metadata during FMU runs (hundreds of thousands of files being made)
Abstract the FMU results data model through Python methods and functions, allowing them to be embedded into other systems - helping maintain a centralized definition of this data model.
The parent/child principle
In the FMU results data model, the traditional hierarchy of an FMU setup is not continued. An individual file produced by an FMU workflow and exported to disk can be seen in relations to a hiearchy looking something like this: case > iteration > realization > file
Many reading this will instinctively disagree with this definition, and significant confusion arises from trying to have meaningful discussions around this. There is no unified definition of this hierarchy (despite many claiming to have such a definition).
In the FMU results data model, this hiearchy is flattened down to two levels: The Parent (case) and children to that parent (files). From this, it follows that the most fundamental definition in this context is a case. To a large degree, this definition belongs to the ERT workflow manager in the FMU context. For now, however, the case definitions are extracted by-proxy from the file structure and from arguments passed to fmu-dataio.
Significant confusion can also arise from discussing the definition of a case, and the validity of this hiearchy, of course. But consensus (albeit probably local minima) is that this serves the needs.
Each file produced in relations to an FMU case (meaning before, during or after) is tagged with information about the case - signalling that this entity belongs to this case. It is not the intention of the FMU results data model to maintain all information about a case, and in the future it is expected that ERT will serve case information beyond the basics.
Note
Dot-annotation - we like it and use it. This is what it means:
The metadata structure is a dictionary-like structure, e.g.
{
"myfirstkey": {
"mykey": "myvalue",
"anotherkey": "anothervalue"
}
}
Annotating tracks along a dictionary can be tricky. With dot-annotation, we can refer to `mykey` in the example above as myfirstkey.mykey. This will be a pointer to myvalue in this case. You will see dot annotation in the explanations of the various metadata blocks below: Now you know what it means!
Weaknesses
uniqueness The data model currently has challenges wrt ensuring uniqueness. Uniqueness is a challenge in this context, as a centralized data model cannot (and should not!) dictate in detail nor define in detail which data an FMU user should be able to export from local workflows.
understanding validation errors When validating against the current schema, understanding the reasons for non-validation can be tricky. The root cause of this is the use of conditional logic in the schemas - a functionality JSON Schema is not designed for. See Logical rules.
Logical rules
The schema contains some logical rules which are applied during validation. These are rules of type “if this, then that”. They are, however, not explicitly written (nor readable) as such directly. This type of logic is implemented in the schema by explicitly generating subschemas that A) are only valid for specific conditions, and B) contain requirements for that specific situation. In this manner, one can assure that if a specific condition is met, the associated requirements for that condition is used.
Example:
"oneOf": [ { "$comment": "Conditional schema A - 'if class == case make myproperty required'", "required": [ "myproperty" ], "properties": { "class": { "enum": ["case"] }, "myproperty": { "type": "string", "example": "sometext" } } }, { "$comment": "Conditional schema B - 'if class != case do NOT make myproperty required'", "properties": { "myproperty": { "type": "string", "example": "sometext" }, } ]
For metadata describing a case, requirements are different compared to metadata describing data objects.
For selected contents, a content-specific block under data is required. This is implemented for “fluid_contact”, “field_outline” and “seismic”.
The metadata structure
Full schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "fmu_results.json",
"$contractual": [
"class",
"source",
"version",
"tracklog",
"data.format",
"data.name",
"data.stratigraphic",
"data.alias",
"data.stratigraphic_alias",
"data.offset",
"data.content",
"data.tagname",
"data.vertical_domain",
"data.grid_model",
"data.bbox",
"data.time",
"data.is_prediction",
"data.is_observation",
"data.seismic.attribute",
"data.spec.columns",
"access",
"masterdata",
"fmu.model",
"fmu.workflow",
"fmu.case",
"fmu.iteration.name",
"fmu.iteration.uuid",
"fmu.realization.name",
"fmu.realization.id",
"fmu.realization.uuid",
"fmu.aggregation.operation",
"fmu.aggregation.realization_ids",
"fmu.context.stage",
"file.relative_path",
"file.checksum_md5",
"file.size_bytes"
],
"definitions": {
"generic": {
"$comment": "GENERIC DEFINITIONS",
"datetime": {
"type": "string",
"examples": [
"2020-10-28T14:28:02"
]
},
"uuid": {
"type": "string",
"pattern": "^[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}$",
"examples": [
"ad214d85-8a1d-19da-e053-c918a4889309"
]
},
"user": {
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"title": "User ID",
"type": "string",
"examples": [
"peesv"
]
}
}
},
"_description": {
"$comment": "Underscore to keep JSON Schema validator functioning",
"type": "array",
"items": {
"type": "string",
"examples": [
"Some description"
]
}
}
},
"fmu_time": {
"title": "FMU time object",
"description": "Time stamp for data object.",
"type": [
"object",
"null"
],
"properties": {
"value": {
"$ref": "#/definitions/generic/datetime"
},
"label": {
"type": "string",
"examples": [
"base",
"monitor",
"mylabel"
]
}
}
},
"class": {
"title": "Metadata class",
"type": "string",
"examples": [
"surface",
"table",
"points"
],
"enum": [
"case",
"surface",
"table",
"cpgrid",
"cpgrid_property",
"polygons",
"cube",
"well",
"points"
]
},
"source": {
"$comment": "Fixed field, only valid value is fmu.",
"description": "Data source (FMU)",
"type": "string",
"const": "fmu"
},
"version": {
"$comment": "Must always be on root level.",
"title": "FMU results metadata version",
"type": "string",
"$comment": "This is 0.8.0, so require version to be == 0.8.0",
"enum": [
"0.8.0"
],
"example": "1.2.3"
},
"tracklog_event": {
"type": "object",
"properties": {
"datetime": {
"$ref": "#/definitions/generic/datetime"
},
"user": {
"$ref": "#/definitions/generic/user"
},
"event": {
"type": "string",
"examples": [
"created",
"updated"
]
}
}
},
"tracklog": {
"type": "array",
"items": {
"$ref": "#/definitions/tracklog_event"
}
},
"data": {
"type": "object",
"title": "The data block",
"required": [
"content",
"name",
"format",
"spec",
"stratigraphic",
"is_prediction",
"is_observation"
],
"dependencies": {
"top": {
"required": [
"base"
]
},
"base": {
"required": [
"top"
]
}
},
"properties": {
"name": {
"type": "string",
"description": "Name of the data object. If stratigraphic, match the entry in the stratigraphic column",
"examples": [
"VIKING GP. Top"
]
},
"stratigraphic": {
"$comment": "Determines of validation against strat column should happen or not",
"type": "boolean",
"description": "True if data object represents an entity in the stratigraphic column",
"examples": [
true
]
},
"alias": {
"type": "array",
"items": {
"$ref": "#/definitions/data/properties/name"
}
},
"stratigraphic_alias": {
"type": "array",
"items": {
"$ref": "#/definitions/data/properties/name"
}
},
"offset": {
"$comment": "To be used if data represents an offset from the specified name",
"$comment": "e.g. a surface representing an offset from a known horizon",
"type": "number",
"example": 11.2
},
"top": {
"$comment": "To be used if data object is an interval",
"properties": {
"name": {
"$ref": "#/definitions/data/properties/name"
},
"stratigraphic": {
"$ref": "#/definitions/data/properties/stratigraphic"
},
"offset": {
"$ref": "#/definitions/data/properties/offset"
}
}
},
"base": {
"$comment": "To be used if data object is an interval",
"properties": {
"name": {
"$ref": "#/definitions/data/properties/name"
},
"stratigraphic": {
"$ref": "#/definitions/data/properties/stratigraphic"
},
"offset": {
"$ref": "#/definitions/data/properties/offset"
}
}
},
"content": {
"type": "string",
"description": "The contents of this data object",
"examples": [
"depth"
]
},
"tagname": {
"type": "string",
"description": "A semi-human readable tag for internal usage and uniqueness",
"examples": [
"ds_extract_geogrid",
"ds_post_strucmod"
]
},
"properties": {
"$comment": "This is not the JSON Schema properties, this is FMU properties",
"description": "data.properties is an array of property objects, representing the properties present in the data object.",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"MyPropertyName"
]
},
"attribute": {
"type": "string",
"examples": [
"MyAttributeName"
]
},
"is_discrete": {
"type": "boolean",
"examples": [
true,
false
]
}
}
}
},
"format": {
"type": "string",
"examples": [
"irap_binary"
]
},
"layout": {
"type": "string",
"examples": [
"regular"
]
},
"unit": {
"type": [
"string",
"null"
],
"examples": [
"m"
]
},
"vertical_domain": {
"type": "string",
"enum": [
"depth",
"time"
],
"examples": [
"depth"
]
},
"depth_reference": {
"type": [
"string",
"null"
],
"examples": [
"msl"
],
"enum": [
"msl",
"sb",
"rkb",
null
]
},
"undef_is_zero": {
"description": "Flag if undefined values are to be interpreted as zero",
"type": "boolean",
"examples": [
"True"
]
},
"grid_model": {
"type": "object",
"properties": {
"name": {
"type": [
"string",
"null"
],
"examples": [
"MyGrid"
]
}
}
},
"spec": {
"type": "object",
"properties": {
"ncol": {
"$comment": "https://json-schema.org/understanding-json-schema/reference/numeric.html",
"type": "integer",
"examples": [
281
]
},
"nrow": {
"type": "integer",
"examples": [
441
]
},
"nlay": {
"type": "integer",
"examples": [
333
]
},
"xori": {
"type": "number",
"examples": [
461499.9997558594
]
},
"yori": {
"type": "number",
"examples": [
5926500.224123242
]
},
"xinc": {
"type": "number",
"examples": [
25.0
]
},
"yflip": {
"type": "integer",
"$comment": "Orientation indicator of coordinate system",
"enum": [
-1,
1
],
"examples": [
-1,
1
]
},
"rotation": {
"type": "number",
"examples": [
"30.00000000231"
]
},
"undef": {
"type": "number",
"$comment": "How is the undefined value represented?",
"examples": [
1.0e+33
]
},
"npolys": {
"description": "The number of individual polygons in the data object",
"type": "integer",
"examples": [
1
]
},
"size": {
"description": "Size of data object.",
"type": "integer",
"examples": [
1,
9999
]
},
"columns": {
"description": "List of columns present in a table.",
"type": "array",
"items": {
"type": "string",
"examples": [
"FOPT",
"STOIIP_OIL",
"COL_1"
]
}
}
}
},
"bbox": {
"type": "object",
"required": [
"xmin",
"xmax",
"ymin",
"ymax"
],
"properties": {
"xmin": {
"type": "number",
"examples": [
456012.5003497944
]
},
"xmax": {
"type": "number",
"examples": [
467540.52762886323
]
},
"ymin": {
"type": "number",
"examples": [
5926499.999511719
]
},
"ymax": {
"type": "number",
"examples": [
5939492.128326312
]
},
"zmin": {
"type": [
"number",
"null"
],
"examples": [
1244.039,
null
]
},
"zmax": {
"type": [
"number",
"null"
],
"examples": [
2302.683,
null
]
}
}
},
"time": {
"type": "object",
"properties": {
"t0": {
"$ref": "#/definitions/fmu_time"
},
"t1": {
"$ref": "#/definitions/fmu_time"
}
}
},
"is_prediction": {
"title": "Is prediction flag",
"$comment": "For flagging predictions, and separating them from non-predictions",
"type": "boolean",
"examples": [
true
]
},
"is_observation": {
"title": "Is observation flag",
"$comment": "For flagging observations, and separating them from non-observations",
"type": "boolean",
"examples": [
true
]
},
"fluid_contact": {
"type": "object",
"description": "Conditional field",
"properties": {
"contact": {
"type": "string",
"enum": [
"owc",
"fwl",
"goc",
"fgl"
],
"$comment": "Not sure if wise to enum this",
"examples": [
"owc",
"fwl"
]
},
"truncated": {
"type": "boolean",
"$comment": "Is this contact truncated to the stratigraphy?",
"examples": [
true
]
}
}
},
"field_outline": {
"description": "Conditional field",
"type": "object",
"required": [
"contact"
],
"properties": {
"contact": {
"type": "string"
}
}
},
"field_region": {
"description": "Conditional field",
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"description": "The ID of the region",
"type": "integer"
}
}
},
"description": {
"$ref": "#/definitions/generic/_description"
},
"seismic": {
"type": "object",
"description": "Conditional field",
"properties": {
"attribute": {
"type": "string",
"examples": [
"amplitude_timeshifted"
]
},
"calculation": {
"type": "string",
"examples": [
"mean"
]
},
"zrange": {
"type": "number",
"examples": [
12.0
]
},
"filter_size": {
"type": "number",
"examples": [
1.0
]
},
"scaling_factor": {
"type": "number",
"examples": [
1.0
]
},
"stacking_offset": {
"type": "string",
"examples": [
"0-15"
]
}
}
}
}
},
"display": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"Top Volantis"
]
},
"subtitle": {
"type": "string",
"examples": [
"Some subtitle"
]
},
"line": {
"type": "object",
"properties": {
"show": {
"type": "boolean",
"examples": [
true
]
},
"color": {
"type": "string",
"examples": [
"black",
"#000000"
]
}
}
},
"points": {
"type": "object",
"properties": {
"show": {
"type": "boolean",
"examples": [
true
]
},
"color": {
"type": "string",
"examples": [
"black",
"#000000"
]
}
}
},
"contours": {
"type": "object",
"properties": {
"show": {
"type": "boolean",
"examples": [
true
]
},
"color": {
"description": "The color of the contour lines",
"type": "string",
"examples": [
"black",
"#000000"
]
},
"increment": {
"description": "The contour increment in same values as the data",
"type": "number",
"examples": [
20.0
]
}
}
},
"fill": {
"type": "object",
"properties": {
"show": {
"type": "boolean",
"examples": [
true
]
},
"color": {
"type": "string",
"examples": [
"black",
"#000000"
]
},
"colormap": {
"$comment": "colormap can be given alongside fill.color. Clients must choose.",
"description": "named reference to a colormap",
"type": "string",
"examples": [
"gist_earth"
]
},
"display_min": {
"description": "The low-side boundary to use for fill color",
"type": "number",
"examples": [
1000.0
]
},
"display_max": {
"description": "The high-side boundary to use for fill color",
"type": "number",
"examples": [
1600.0
]
}
}
}
}
},
"access": {
"type": "object",
"properties": {
"asset": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Drogon"
]
}
}
},
"ssdl": {
"type": "object",
"$comment": "Required for data objects",
"required": [
"access_level",
"rep_include"
],
"properties": {
"access_level": {
"$comment": "'asset' is legacy, but will be allowed in a transition",
"type": "string",
"enum": [
"internal",
"restricted",
"asset"
]
},
"rep_include": {
"$comment": "Should REP display this data?",
"type": "boolean",
"examples": [
true,
false
]
}
}
},
"classification": {
"type": "string",
"enum": [
"internal",
"restricted"
],
"examples": [
"internal",
"restricted"
]
}
}
},
"masterdata": {
"$comment": "Block holds references to master data",
"type": "object",
"required": [
"smda"
],
"properties": {
"smda": {
"type": "object",
"required": [
"country",
"discovery",
"field",
"coordinate_system",
"stratigraphic_column"
],
"properties": {
"country": {
"$comment": "Array of SMDA-valid countries. First entry is primary.",
"type": "array",
"items": {
"type": "object",
"required": [
"identifier",
"uuid"
],
"properties": {
"identifier": {
"type": "string",
"examples": [
"Norway"
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
}
}
}
},
"discovery": {
"$comment": "Array of SMDA-valid discoveries. First entry is primary.",
"type": "array",
"items": {
"type": "object",
"required": [
"short_identifier",
"uuid"
],
"properties": {
"short_identifier": {
"type": "string",
"examples": [
"SomeDiscovery"
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
}
}
}
},
"field": {
"$comment": "Array of SMDA-valid (oil & gas) fields. First entry is primary.",
"type": "array",
"items": {
"type": "object",
"required": [
"identifier",
"uuid"
],
"properties": {
"identifier": {
"type": "string",
"examples": [
"OseFax"
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
}
}
}
},
"coordinate_system": {
"$comment": "SMDA-valid coordinate system.",
"type": "object",
"required": [
"identifier",
"uuid"
],
"properties": {
"identifier": {
"type": "string",
"examples": [
"ST_WGS84_UTM37N_P32637"
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
}
}
},
"stratigraphic_column": {
"$comment": "SMDA-valid stratigraphic column.",
"type": "object",
"required": [
"identifier",
"uuid"
],
"properties": {
"identifier": {
"type": "string",
"examples": [
"DROGON_2020"
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
}
}
}
}
}
}
},
"fmu": {
"model": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"Drogon"
]
},
"revision": {
"type": "string",
"examples": [
"21.0.0.dev"
]
},
"description": {
"description": "This is a free text description of the model setup",
"$ref": "#/definitions/generic/_description"
}
}
},
"workflow": {
"type": "object",
"properties": {
"reference": {
"type": "string",
"description": "Reference to the part of the FMU workflow that produced this"
}
}
},
"case": {
"type": "object",
"required": [
"name",
"uuid",
"user"
],
"properties": {
"name": {
"type": "string",
"description": "The case name",
"examples": [
"MyCaseName"
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
},
"user": {
"description": "The user name used in ERT",
"$ref": "#/definitions/generic/user"
},
"description": {
"$ref": "#/definitions/generic/_description"
}
}
},
"iteration": {
"type": "object",
"required": [
"name",
"uuid"
],
"properties": {
"name": {
"description": "The convential name of this iteration, e.g. iter-0 or pred",
"type": "string",
"examples": [
"iter-0"
]
},
"id": {
"description": "The internal identification of this iteration, e.g. the iteration number",
"type": "integer",
"examples": [
0
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
},
"restart_from": {
"description": "A uuid reference to another iteration that this iteration was restarted from",
"$ref": "#/definitions/generic/uuid"
}
}
},
"realization": {
"$comment": "Some schema repetition between realization and aggregation",
"type": "object",
"required": [
"name",
"id",
"uuid"
],
"properties": {
"name": {
"description": "The convential name of this iteration, e.g. iter-0 or pred",
"type": "string",
"examples": [
"iter-0"
]
},
"id": {
"type": "integer",
"description": "The unique number of this realization as used in FMU",
"examples": [
33
]
},
"uuid": {
"$ref": "#/definitions/generic/uuid"
},
"parameters": {
"type": "object",
"description": "Parameters for this realization",
"items": {
"type": "object"
}
},
"jobs": {
"type": "object",
"description": "Content directly taken from the ERT jobs.json file for this realization"
}
}
},
"aggregation": {
"$comment": "Some schema repetition between realization and aggregation",
"type": "object",
"required": [
"operation",
"realization_ids"
],
"properties": {
"operation": {
"type": "string",
"description": "The aggregation performed"
},
"realization_ids": {
"type": "array",
"description": "Array of realization ids included in this aggregation",
"items": {
"type": "integer",
"examples": [
0,
1,
2,
3
]
}
},
"parameters": {
"type": "object",
"description": "Parameters for this realization",
"items": {
"type": "object"
}
},
"id": {
"type": "string",
"description": "The ID of this aggregation",
"$comment": "Used for tying together representations of the same entity",
"$comment": "Example: Statistics for various time steps of the same surface",
"$comment": "Not used in Drogon but widely used on e.g. Johan Sverdrup",
"$comment": "Used for enabling common display and joint visual settings",
"$comment": "A unique uuid is currently used, and included as example but any ID should be sufficient",
"examples": [
"15ce3b84-766f-4c93-9050-b154861f9100"
]
}
}
},
"context": {
"description": "The internal FMU context in which this data object was produced",
"type": "object",
"required": [
"stage"
],
"properties": {
"stage": {
"type": "string",
"examples": [
"case",
"iteration",
"realization"
]
}
}
}
},
"file": {
"description": "Block describing the file as the data appear in FMU context",
"$comment": "While the file may seize to exist, the concept is still useful",
"$comment": "A lot of logic exists on top of the file name now, legacy but not likely to disappear soon",
"type": "object",
"required": [
"relative_path",
"checksum_md5"
],
"properties": {
"relative_path": {
"type": "string",
"description": "The file path relative to RUNPATH",
"examples": [
"share/results/maps/volantis_gp_base--depth.gri"
]
},
"absolute_path": {
"type": "string",
"description": "The absolute file path",
"examples": [
"/abs/path/share/results/maps/volantis_gp_base--depth.gri"
]
},
"checksum_md5": {
"description": "md5 checksum of the file or bytestring",
"type": "string",
"examples": [
"kjhsdfvsdlfk23knerknvk23"
]
},
"size_bytes": {
"description": "Size of file object in bytes",
"type": "integer",
"examples": [
123
]
}
}
}
},
"$comment": "DEFINITIONS END HERE",
"$comment": "oneOf below reflects different structures depending on type",
"$comment": "The fmu-block is different for cases and data objects,",
"$comment": "and the data block is only present for data objects.",
"required": [
"source",
"version",
"class",
"fmu",
"access",
"tracklog",
"masterdata"
],
"properties": {
"source": {
"$ref": "#/definitions/source"
},
"version": {
"$ref": "#/definitions/version"
},
"data": {
"$ref": "#/definitions/data"
},
"tracklog": {
"$ref": "#/definitions/tracklog"
},
"access": {
"$ref": "#/definitions/access"
},
"masterdata": {
"$ref": "#/definitions/masterdata"
},
"class": {
"$ref": "#/definitions/class"
}
},
"oneOf": [
{
"$comment": "Valid when class == case)",
"properties": {
"class": {
"enum": [
"case"
]
},
"fmu": {
"description": "The FMU block records properties that are specific to FMU",
"$comment": "This is the fmu block as it appears in data objects",
"type": "object",
"required": [
"model",
"case"
],
"properties": {
"model": {
"$ref": "#/definitions/fmu/model"
},
"case": {
"$ref": "#/definitions/fmu/case"
}
}
},
"access": {
"required": [
"asset"
]
}
}
},
{
"$comment": "Valid when class != case",
"required": [
"data",
"file"
],
"properties": {
"class": {
"not": {
"enum": [
"case"
]
}
},
"fmu": {
"description": "The FMU block records properties that are specific to FMU",
"$comment": "This is the fmu block as it appears in data objects",
"required": [
"model",
"case"
],
"properties": {
"model": {
"$ref": "#/definitions/fmu/model"
},
"case": {
"$ref": "#/definitions/fmu/case"
},
"iteration": {
"$ref": "#/definitions/fmu/iteration"
},
"realization": {
"$ref": "#/definitions/fmu/realization"
},
"workflow": {
"$ref": "#/definitions/fmu/workflow"
},
"aggregation": {
"$ref": "#/definitions/fmu/aggregation"
}
},
"$comment": "implementation below allows realization or aggregation or none of them, never both",
"dependencies": {
"aggregation": {
"not": {
"required": [
"realization"
]
}
},
"realization": {
"not": {
"required": [
"aggregation"
]
}
}
}
},
"file": {
"$ref": "#/definitions/file"
},
"data": {
"$comment": "Conditionals",
"allOf": [
{
"$comment": "When content == field_outline, require data.field_outline",
"if": {
"properties": {
"content": {
"const": "field_outline"
}
}
},
"then": {
"required": [
"field_outline"
]
}
},
{
"$comment": "When content == field_region, require data.field_region",
"if": {
"properties": {
"content": {
"const": "field_region"
}
}
},
"then": {
"required": [
"field_region"
]
}
},
{
"$comment": "When content == fluid_contact, require data.fluid_contact",
"if": {
"properties": {
"content": {
"const": "fluid_contact"
}
}
},
"then": {
"required": [
"fluid_contact"
]
}
},
{
"$comment": "When content == seismic, require data.seismic",
"if": {
"properties": {
"content": {
"const": "seismic"
}
}
},
"then": {
"required": [
"seismic"
]
}
}
]
},
"access": {
"required": [
"asset",
"ssdl"
]
}
}
}
]
}
For the average user, there is no need to deep-dive into the schema itself. The purpose of fmu-dataio is to broker between the different other data models used in FMU, and the definitions of FMU results. E.g. RMS has its data model, Eclipse has its data model, ERT has its data model, and so on.
What you need to know is that for every data object exported out of FMU with the intention of using in other contexts a metadata instance pertaining to this definition will also be created.
Outgoing metadata for an individual data object (file) in the FMU context will contain the relevant root attributes and blocks described further down this document. Not all data objects will contain all attributes and blocks - this depends on the data type, the context it is exported in and the data available.
Example: Data produced by pre- or post-processes will contain information about the case but
not about realization implicitly meaning that they belong to a specific
case but not any specific realizations.
Note
The case object is a bit special: It represents the parent object, and records
information about the case only. It follows the same patterns as for individual data objects
but will not contain the data block which is mandatory for data objects.
Root attributes
At the root level of the metadata, a few single-value attributes are used. These are attributes saying something fundamental about these data:
$schema: A reference to the schema which this metadata should be valid against.
version: The version of the FMU results data model being used.
source: The source of these data. Will always say “fmu” for FMU results.
class: The fundamental type of data. Valid classes: * case * surface * table * cpgrid * cpgrid_property * polygons * cube * well * points
Blocks
The bulk of the metadata is gathered in specific blocks. Blocks are sub-dictionaries containing a specific part of the metadata. Not all blocks are present in all materialized metadata, and not all block sub-attributes are applied in all contexts.
fmu
The fmu block contains all attributes specific to FMU. The idea is that the FMU results
data model can be applied to data from other sources - in which the fmu-specific stuff
may not make sense or be applicable. Within the fmu-block, there are more blocks:
fmu.model: The fmu.model block contains information about the model used.
Note
Synonyms for “model” in this context are “template”, “setup”, etc. The term “model” is ultra-generic but was chosen before e.g. “template” as the latter deviates from daily communications and is, if possible, even more generic than “model”.
fmu.workflow: The fmu.workflow block refers to specific subworkflows within the large
FMU workflow being ran. This has not (yet?) been standardized, mainly due to the lack
of programmatic access to the workflows being run in important software within FMU.
One sub-attribute has been defined and is used:
fmu.workflow.reference: A string referring to which workflow this data object was exported by.
Note
A key usage of fmu.workflow.reference is related to ensuring uniqueness of data objects.
Example of uniqueness challenge During an hypothetical FMU workflow, a surface representing a specific horizon in depth is exported multiple times during the run for QC purposes. E.g. a representation of Volantis Gp. Top is first exported at the start of the workflow, then 2-3 times during depth conversion to record changes, then at the start of structural modeling, then 4-5 times during structural modeling to record changes, then extracted from multiple grids.
The end result is 10+ versions of Volantis Gp. Top which are identical except from which workflow they were produced by.
fmu.case: The fmu.case block contains information about the case from which this data
object was exported. fmu.case has the following subattributes, and more may arrive:
fmu.case.name: [string] The name of the case
fmu.case.uuid: [uuid] The unique identifier of this case. Currently made by fmu.dataio. Future made by ERT?
fmu.case.user: A block holding information about the user.
fmu.case.user.id: [string] A user identity reference.
fmu.case.description: [list of strings] (a free-text description of this case) (optional)
Note
If an FMU data object is exported outside the case context, this block will not be present.
fmu.iteration: The fmu.iteration block contains information about the iteration this data object belongs to. The fmu.iteration
has the following defined sub-attributes:
fmu.iteration.id: [int] The internal ID of the iteration, typically represented by an integer.
fmu.iteration.uuid: [uuid] The universally unique identifier for this iteration. It is a hash of
fmu.case.uuidandfmu.iteration.id.fmu.iteration.name: [string] The name of the iteration. This is typically reflecting the folder name on scratch. In ERT, custom names for iterations are supported, e.g. “pred”. For this reason, if logic is implied, the name can be risky to trust - even if it often contains the ID, e.g. “iter-0”
fmu.iteration.restart_from: [uuid] The intention with this attribute is to flag when a iteration is a restart fromm another iteration.
fmu.realization: The fmu.realization block contains information about the realization this data object belongs to, with the following sub-attributes:
fmu.realization.id: The internal ID of the realization, typically represented by an integer.
fmu.realization.uuid: The universally unique identifier for this realization. It is a hash of
fmu.case.uuidandfmu.iteration.uuidandfmu.realization.id.fmu.realization.name: The name of the realization. This is typically reflecting the folder name on scratch. Custom names for realizations are not supported by ERT, but we still recommend to use
fmu.realization.idfor all usage except purely visual appearance.fmu.realization.parameters: These are the parameters used in this realization. It is a direct pass of
parameters.txtand will contain key:value pairs representing the design parameters.
fmu.jobs: Directly pass “jobs.json”. Temporarily deactivated in fmu-dataio pending further alignment with ERT.
Note
The blocks within the fmu section signal by their presence which context a data object is exported under. Example: If an
aggregated object contains fmu.case and fmu.iteration, but not fmu.realization, it can be assumed that this object belongs
to this case and iteration but not to any specific realization.
file
The file block contains references to this data object as a file on a disk. A filename
in this context can be actual, or abstract. Particularly the relative_path is, and will
most likely remain, an important identifier for individual file objects within an FMU
case - irrespective of the existance of an actual file system. For this reason, the
relative_path - as well as the checksum_md5 will be generated even if a file is
not saved to disk. The absolute_path will only be generated in the case of actually
creating a file on disk and is not required under this schema.
file.relative_path: [path] The path of a file relative to the case root.
file.absolute_path: [path] The absolute path of a file, e.g. /scratch/field/user/case/etc
file.checksum_md5: [string] A valid MD5 checksum of the file.
data
The data block contains information about the data contains in this object.
data.content: [string] The content of these data. Examples are “depth”, “porosity”, etc.
data.name: [string] This is the identifying name of this data object. For surfaces, this is typically the horizon name or similar. Shall be compliant with the stratigraphic column if applicable.
data.stratigraphic: [bool] True if this is defined in the stratigraphic column.
data.offset: If a specific horizon is represented with an offset, e.g. “2 m below Top Volantis”.
Note
If data object represents an interval, the data.top and data.base attributes can be used.
data.top:
data.top.name: As data.name
data.top.stratigraphic: As data.stratigraphic
data.top.offset: As data.offset
data.base:
data.base.name: As data.name
data.base.stratigraphic: As data.stratigraphic
data.base.offset: As data.offset
data.stratigraphic_alias: [list] A list of strings representing stratigraphic aliases for this data.name. E.g. the top of the uppermost member of a formation will be alias to the top of the formation.
data.alias: [list] Other known-as names for data.name. Typically names used within specific software, e.g. RMS and others.
data.tagname: [string] An identifier for this/these data object(s). Similar to the second part of the generated filename in disk-oriented FMU data standard.
data.properties: A list of dictionary objects, where each object describes a property contained by this data object.
data.properties.<item>.name: [string] The name of this property.
data.properties.<item>.attribute: [string] The attribute.
data.properties.<item>.is_discrete: [bool] Flag if this property is is_discrete.
data.properties.<item>.calculation: [string] A reference to a calculation performed to derive this property.
Note
The data.properties concept is experimental. Use cases include surfaces containing multiple properties/attributes, grids with parameters, etc.
data.format: [string] A reference to a known file format.
data.layout: [string] A reference to the layout of the data object. Examples: “regular”, “cornerpoint”, “structured”
data.unit: [string] A reference to a known unit. Examples. “m”
data.vertical_domain: [string] A reference to a known vertical domain. Examples: “depth”, “time”
data.depth_reference: [string] A reference to a known depth reference. Examples: “msl”, “seabed”
data.grid_model: A block containing information pertaining to grid model content.
data.grid_model.name: [string] A name reference to this data.
data.spec: A block containing the specs for this object, if applicable.
data.spec.ncol: [int] Number of columns
data.spec.nrow: [int] Number of rows
data.spec.nlay: [int] Number of layers
data.spec.xori: [float] Origin X coordinate
data.spec.yori: [float] Origin Y coordinate
data.spec.xinc: [float] X increment
data.spec.yinc: [float] Y increment
data.spec.yflip: [int] Y flip flag (from IRAP Binary)
data.spec.rotation: [float] Rotation (degrees)
data.spec.undef: [float] Number representing the Null value
data.bbox: A block containing the bounding box for this data, if applicable
data.bbox.xmin: [float] Minimum X coordinate
data.bbox.xmax: [float] Maximum X coordinate
data.bbox.ymin: [float] Minimum Y coordinate
data.bbox.ymax: [float] Maximum Y coordinate
data.bbox.zmin: [float] Minimum Z coordinate
data.bbox.zmax: [float] Maximum Z coordinate
data.time: A block containing lists of objects describing timestamp information for this data object, if applicable.
data.time.value: [datetime] A datetime representation
data.time.label: [string] A label corresponding to the timestamp
Note
data.time items can be repeated to include many time stamps
data.is_prediction: [bool] True if this is a prediction
data.is_observation: [bool] True if this is an observation
data.description: [list] A list of strings, freetext description of this data, if applicable.
Conditional attributes of the data block:
data.fluid_contact: A block describing a fluid contact. Shall be present if “data.content” == “fluid_contact”
data.fluid_contact.contact: [string] A known type of contact. Examples: “owc”, “fwl”
data.fluid_contact.truncated: [bool] If True, this is a representation of a contact surface which is truncated to stratigraphy.
data.field_outline: A block describing a field outline. Shall be present if “data.content” == “field_outline”
data.field_outline.contact: The fluid contact used to define the field outline.
data.seismic: A block describing seismic data. Shall be present if “data.content” == “seismic”
data.seismic.attribute: [string] A known seismic attribute.
data.seismic.zrange: [float] The z-range applied.
data.seismic.filter_size: [float] The filter size applied.
data.seismic.scaling_factor: [float] The scaling factor applied.
display
The display block contains information related to how this data object should/could be displayed.
As a general rule, the consumer of data is responsible for figuring out how a specific data object shall
be displayed. However, we use this block to communicate preferences from the data producers perspective.
We also maintain this block due to legacy reasons. No data filtering logic should be placed on the display block.
display.name: A display-friendly version of
data.name.display.subtitle: A display-friendly subtitle.
display.line: (Experimental) A block containing display information for line objects.
display.line.show: [bool] Show a line
display.line.color: [string] A reference to a known color.
display.points: (Experimental) A block containing display information for point(s) objects.
display.points.show: [bool] Show points.
display.points.color: [string] A reference to a known color.
display.contours: (Experimental) A block containing display information for contours.
display.contours.show: [bool] Show contours.
display.contours.color: [string] A reference to a known color.
display.fill: (Experimental) A block containing display information for fill.
display.fill.show: [bool] Show fill.
display.fill.color: [string] A reference to a known color.
display.fill.colormap: [string] A reference to a known color map.
display.fill.display_min: [float] The value to use as minimum value when displaying.
display.fill.display_max: [float] The value to use as maximum value when displaying.
access
The access block contains information related to acces control for this data object.
asset: A block containing information about the owner asset of these data.
access.asset.name: [string] A string referring to a known asset name.
access.ssdl: A block containing information related to SSDL. Note that this is kept due to legacy.
access.ssdl.access_level: [string] The SSDL access level (internal/asset)
access.ssdl.rep_include: [bool] Flag if this data is to be shown in REP or not.
We fully acknowledge that horrible pattern of putting application-specific information into a data model like this. However for legacy reasons this is kept until better options exists.
masterdata
The masterdata block contains information related to masterdata. Currently, smda holds the masterdata.
masterdata.smda: Block containing SMDA-related attributes.
masterdata.smda.country: [list] A list of strings referring to countries known to SMDA. First item is primary.
masterdata.smda.discovery: [list] A list of strings referring to discoveries known to SMDA. First item is primary.
masterdata.smda.field: [list] A list of strings referring to fields known to SMDA. First item is primary.
masterdata.smda.coordinate_system: Reference to coordinate system known to SMDA
masterdata.smda.coordinate_system.identifier: [string] Identifier known to SMDA
masterdata.smda.coordinate_system.uuid: [uuid] A UUID known to SMDA
masterdata.smda.stratigraphic_column: Reference to stratigraphic column known to SMDA
masterdata.smda.stratigraphic_column.identifier: [string] Identifier known to SMDA
masterdata.smda.stratigraphic_column.uuid: [uuid] A UUID known to SMDA
tracklog
The tracklog block contains a record of events recorded on these data. This is experimental for now. The tracklog is a list of tracklog_events with the following definition:
tracklog.<tracklog_event>: An event. * tracklog.<tracklog_event>.datetime: [datetime] Timestamp of the event * tracklog.<tracklog_event>.user: [string] Identification of user associated with the event * tracklog.<tracklog_event>.event: [string] String representing the event
Note
The “tracklog” concept is included but considered heavily experimental for now. The concept of data lineage goes far beyond this, and this should not be read as the full lineage of these data.
Changes and revisions
The only constant is change, as we know, and in the case of the FMU results data model - definitely so. The learning component here is huge, and there will be iterations. This poses a challenge, given that there are existing dependencies on top of this data model already, and more are arriving.
To handle this, two important concepts has been introduced.
Versioning. The current version of the FMU metadata is 0.8.0. This version is likely to remain for a while. (We have not yet figured out how to best deal with versioning. Have good ideas? Bring them!)
Contractual attributes. Within the FMU ecosystem, we need to retain the ability to do rapid changes to the data model. As we are in early days, unknowns will become knowns and unknown unknowns will become known unknowns. However, from the outside perspective some stability is required. Therefore, we have labelled some key attributes as contractual. They are listed at the top of the schema. This is not to say that they will never change - but they should not change erratically, and when we need to change them, this needs to be subject to alignment.
Contractual attributes
The following attributes are contractual:
class
source
version
tracklog
data.format
data.name
data.stratigraphic
data.alias
data.stratigraphic_alias
data.offset
data.content
data.vertical_domain
data.grid_model
data.bbox
data.is_prediction
data.is_observation
data.seismic.attribute
access
masterdata
fmu.model
fmu.workflow
fmu.case
fmu.iteration
fmu.realization.name
fmu.realization.id
fmu.realization.uuid
fmu.aggregation.operation
fmu.aggregation.realization_ids
file.relative_path
file.checksum_md5
Metadata example
Expand below to see a full example of valid metadata for surface exported from FMU.
# Example metadata for a depth surface.
$schema: https://main-fmu-schemas-dev.radix.equinor.com/schemas/0.8.0/fmu_results.json
version: "0.8.0" # including for REP and others to build logic on.
source: fmu # always included, and always this value if FMU made it. For quick identification for external consumers.
tracklog:
- datetime: 2020-10-28T14:28:02
user:
id: peesv
event: created
- datetime: 2020-10-28T14:46:14
user:
id: peesv
event: updated
class: surface # class is the main identifier of the data type.
fmu: # the fmu-block contains information directly related to the FMU context
model:
name: ff
revision: 21.0.0.dev
description:
- detailed description
- optional
workflow:
reference: rms/structural_model
case:
name: MyCaseName
uuid: 8bb56d60-8758-481a-89a4-6bac8561d38e
user:
id: jriv # $USER from ERT
description:
- yet other detailed description
- optional
iteration:
id: 0 # always an int, will be 0 for e.g. "pred"
uuid: 4b939310-34b1-4179-802c-49460bc0f799 # hash of case.uuid + iteration.id
name: "iter-0" # /"pred"
restart_from: 15ce3b84-766f-4c93-9050-b154861f9100 # fmu.iteration.uuid for another iteration
realization:
id: 33
uuid: 29a15b21-ce13-471b-9a4a-0f791552aa51
name: "realization-33"
parameters: # directly pass parameters.txt. This is potentially a lot of content, only a stub is included here.
SENSNAME: faultseal
SENSCASE: low
RMS_SEED: 1006
INIT_FILES:
PERM_FLUVCHAN_E1_NORM: 0.748433
PERM_FLUVCHAN_E21_NORM: 0.782068
KVKH_CHANNEL: 0.6
KVKH_US: 0.6
FAULT_SEAL_SCALING: 0.1
FWL_CENTRAL: 1677
context:
stage: realization
file:
relative_path: realization-33/iter-0/share/results/maps/volantis_gp_base--amplitude.gri # case-relative
absolute_path: /some/absolute/path/realization-33/iter-0/share/results/maps/volantis_gp_base--amplitude.gri
checksum_md5: kjhsdfvsdlfk23knerknvk23 # checksum of the file, not the data.
size_bytes: 132321
data: # The data block describes the actual data (e.g. surface). Only present in data objects
content: depth # white-listed and standardized
# if stratigraphic, name must match the strat column. This is the official name of this surface.
name: volantis_top-volantis_base
stratigraphic: false # if true, this is a stratigraphic surface found in the strat column
offset: 0.0 # to be used if a specific horizon is represented with an offset.
top: # not required, but allowed
name: volantis_gp_top
stratigraphic: true
offset: 2.0
base:
name: volantis_gp_top
stratigraphic: true
offset: 8.3
stratigraphic_alias: # other stratigraphic entities this corresponds to in the strat column, e.g. Top Viking vs Top Draupne. Ref issue.
- SomeName Fm. 1 Top
alias: # other known-as names, such as name used inside RMS etc
- somename_fm_1_top
- top_somename
# tagname is flexible. The tag is intended primarily for providing uniqueness. The tagname will also be part of the outgoing file name on disk.
tagname: ds_extract_geogrid
# no content-specific attribute for "depth" but can come in the future
properties: # what the values actually show. List, only one for IRAP Binary surfaces. Multiple for 3d grid or multi-parameter surfaces. First is geometry.
- name: PropertyName
attribute: owc
is_discrete: false # to be used for discrete values in surfaces.
calculation: null # max/min/rms/var/maxpos/sum/etc
format: irap_binary
layout: regular # / cornerpoint / structured / etc
unit: m
vertical_domain: depth # / time / null
depth_reference: msl # / seabed / etc
grid_model: # Making this an object to allow for expanding in the future
name: MyGrid # important for data identification, also important for other data types
spec: # class/layout dependent, optional? Can spec be expanded to work for all data types?
ncol: 281
nrow: 441
nlay: 333
xori: 461499.9997558594
yori: 5926500.0
xinc: 25.0
yinc: 25.0
yflip: 1
rotation: 30.000000834826057
undef: 1.0e+33 # Allow both number and string
bbox:
xmin: 456012.5003497944
xmax: 467540.52762886323
ymin: 5926499.999511719
ymax: 5939492.128326312
zmin: 1244.039
zmax: 2302.683
is_prediction: true # A mechanism for separating pure QC output from actual predictions
is_observation: true # Used for 4D data currently but also valid for other data?
undef_is_zero: false # Used to flag if undef should be considered 0.0 in statistics
description:
- Depth surfaces extracted from the structural model
- Made in a FMU work flow
display:
name: Top Volantis
subtitle: Some subtitle
line:
show: true
color: black
style: solid
points:
show: false
color: null
contours:
show: true
color: black
increment: 20
fill:
show: true
color: black # color and colormap are mutually exclusive in practice, so clients must choose.
colormap: gist_earth
display_min: 1221.3
display_max: 1900.0
access:
asset:
name: Drogon
ssdl:
access_level: internal
rep_include: true
classification: internal
masterdata:
smda:
country:
- identifier: Norway
uuid: ad214d85-8a1d-19da-e053-c918a4889309
discovery:
- short_identifier: DROGON
uuid: 00000000-0000-0000-0000-000000000000 # mock uuid for Drogon
field:
- identifier: DROGON
uuid: 00000000-0000-0000-0000-000000000000 # mock uuid for Drogon
coordinate_system:
identifier: ST_WGS84_UTM37N_P32637
uuid: ad214d85-dac7-19da-e053-c918a4889309
stratigraphic_column:
identifier: DROGON_2020
uuid: 00000000-0000-0000-0000-000000000000 # mock uuid for Drogon
You will find more examples in fmu-dataio github repository.
FAQ
We won’t claim that these questions are really very frequently asked, but these are some key questions you may have along the way.
My existing FMU workflow does not produce any metadata. Now I am told that it has to. What do I do? First step: Start using fmu-dataio in your workflow. You will get a lot for free using it, amongst other things, metadata will start to appear from your workflow. To get started with fmu-dataio, see the overview section.
This data model is not what I would have chosen. How can I change it? The FMU community (almost always) builds what the FMU community wants. The first step would be to define what you are unhappy with, preferably formulated as an issue in the fmu-dataio github repository. (If your comments are Equinor internal, please reach out to either Per Olav (peesv) or Jan (jriv).)
This data model allows me to create a smashing data visualisation component, but I fear that it is so immature that it will not be stable - will it change all the time? Yes, and no. It is definitely experimental and these are early days. Therefore, changes will occur as learning is happening. Part of that learning comes from development of components utilizing the data model, so your feedback may contribute to evolving this data model. However, you should not expact erratic changes. The concept of Contractual attributes are introduced for this exact purpose. We have also chosen to version the metadata - partly to clearly separate from previous versions, but also for allowing smooth evolution going forward. We don’t yet know exactly how this will be done in practice, but perhaps you will tell us!