Anda di halaman 1dari 98

Getting Started with Ocean

For Geoscientists and Software Developers

Published by Schlumberger Information Solutions,


5599 San Felipe, Houston Texas 77056

Index

Copyright Notice

Copyright 2005-2013 Schlumberger. All rights reserved.

The information in this document is subject to change without notice. The software
described in this document is furnished under a license agreement. This software may
be used or copied only in accordance with the terms of such agreement. It is against the
law to copy the software on any medium except as specifically allowed in the license
agreement. No part of this document may be reproduced or transmitted in any form, or
by any means, electronic or mechanical, including photocopying and recording, for any
purpose without the express written permission of Schlumberger.

Trademarks

Petrel and Ocean are trademarks of Schlumberger.


Microsoft and Windows are registered trademarks of Microsoft Corporation.

ii

Welcome to Ocean for Petrel

TABLE OF CONTENTS
Welcome to Ocean for Petrel ................................................................ 4
Ocean Architecture ................................................................................................ 4
Access to the Petrel Data Domain .......................................................................... 5
Ocean for Petrel UI Infrastructure ......................................................................... 5
The Ocean Plug-in and Module .............................................................................. 6
Plugin class..................................................................................................... 7
IModule Interface .......................................................................................... 7
Writing Your First Plug-In ...................................................................10
Writing the Plug-in ............................................................................................... 10
Creating the Plugin, Module and Process with Visual Studio ...................... 10
Inspecting the Files ...................................................................................... 15
Writing the Algorithm Code ........................................................................ 16
Running the Plug-in .............................................................................................. 18
Using the Online Help........................................................................................... 20
Opening the Online Help ............................................................................. 20
Using IntelliSense......................................................................................... 20
Accessing Class Definitions .......................................................................... 21
Understanding the Petrel Data Domain...............................................22
Exposing Petrels Data Model .............................................................................. 22
Entities and Properties ................................................................................ 22
User View of the Petrel Data Model ............................................................ 22
Data Access .......................................................................................................... 27
Data Types Exposed ..................................................................................... 27
Read Access .......................................................................................................... 28
Browsing Collections.................................................................................... 28

Welcome to Ocean for Petrel

Seismic Data................................................................................................. 28
Well and Geology......................................................................................... 29
Pillar Grid Model .......................................................................................... 30
Simulation and Data Analysis ...................................................................... 31
Updating Data ...................................................................................................... 31
Using Transactions ....................................................................................... 31
Modifying Domain Objects .......................................................................... 32
Accessing Domain Object Relationships ...................................................... 32
Domain Object Creation ....................................................................................... 33
Creating New Instances ............................................................................... 33
Creating New Collections............................................................................. 34
Deleting Objects ................................................................................................... 35
Accessing Data: Examples .................................................................................... 35
Browsing Well Logs ...................................................................................... 36
Retrieving Models........................................................................................ 36
Creating New Property Collections ............................................................. 37
Creating the Pillar Grid Property ................................................................. 37
Filling Values ................................................................................................ 37
Extending the Petrel UI ........................................................................38
Adding a New Menu Item .................................................................................... 38
Editing the IntegratePresentation Method ................................................. 38
Creating UI Tools ......................................................................................... 38
Defining the Menu Item Properties ............................................................. 39
Adding the Item to the Menu ...................................................................... 40
Viewing the Results .............................................................................................. 41
Extending the Data Domain .................................................................42
Basic Custom Domain Object ............................................................................... 42
Adding to Input and Models Trees ....................................................................... 43
Adding to Native Petrel Domain Objects ..................................................... 43
Adding an Object from a Context Menu...................................................... 44
Customizing Tree Presentation ................................................................... 45
Rendering a Custom Domain Object .................................................................... 46
3D Window Display...................................................................................... 46
Map Window Display................................................................................... 48
Saving Custom Domain Objects ........................................................................... 49
Structured Archive Data Source .................................................................. 50
Appendix The Ocean Wizard ...............................................................52
2

Welcome to Ocean for Petrel

Installing the Ocean Wizard ................................................................................. 52


Creating an Ocean Plug-in Project........................................................................ 54
Adding a New Process .......................................................................................... 58
Adding a New Petrel Menu Extension.................................................................. 62
Adding a New Petrel Tree Extension .................................................................... 64
Adding a New Window ......................................................................................... 66
Adding a New Workstep....................................................................................... 67
Adding an Ocean Settings Page ............................................................................ 69
Adding Ocean Data Sources ................................................................................. 70
Adding an Ocean Seismic Attribute...................................................................... 71
Adding an ECLIPSE Format Simulator Plug-in....................................................... 72
Adding a Plug-in project ....................................................................................... 76
Adding a New Property Modeling Algorithm ....................................................... 78
Geometrical modeling algorithm ................................................................ 79
Facies modeling algorithm........................................................................... 80
Petrophysical modeling algorithm............................................................... 81
Adding a PIP Project ............................................................................................. 81
Editing the DeployList.xml .................................................................................... 83
Adding Ocean Plug-in Installer Project ................................................................. 84
Adding Ocean Wix Plug-in Installer Project.......................................................... 88
Customizing the PluginInstallInfo.xml ......................................................... 93
Creating an Ocean Plug-in Test Project ................................................................ 93

Welcome to Ocean for Petrel

WELCOME TO OCEAN FOR PETREL


Ocean is an application development framework with the capability to work across data
domains. It provides services, components, and a common graphical user interface that enables
efficient integration between applications. It allows application developers to interact with
Ocean applications like Petrel.
Ocean applications are loaded dynamically as .NET assemblies. These assemblies, the building
blocks of Ocean, contain modules. Plug-ins organize and contain modules.

Ocean Architecture
The Ocean architecture consists of three levels: the Core, the Services, and the product family.
For model-centric applications, the product family is Petrel. Ocean modules are managed by the
Core layer. They interact with all levels of the framework, as shown in Figure 1:

Application Module
Deployed as plug-in or extension module
Schlumberger or 3rd party

Product Family

Ocean Services

Ocean Core
Figure 1: Ocean Architecture

The Ocean Core plays the role of the basic infrastructure. It manages Ocean modules and
registers services, both the services pre-loaded by the product family as well as services that are
added dynamically via the application programming interface (API). The Ocean Core manages
the data sources provided by the product family or any external data source that could be
defined by any module. It also performs event management and basic message logging.
The Ocean Services are a set of application independent utilities. They are modules that benefit
from being standardized across product families. An example is the Coordinate Service a utility
for converting between projection and geodetic coordinate systems. The Ocean Services layer
only depends on the Ocean Core or on other Ocean Services.
The product family is the host for Ocean applications and is the environment in which the Ocean
module needs to run. The product family provides:

Welcome to Ocean for Petrel

the domain objects and their data source

the graphical environment in which the applications will display their data

a common look and feel for all application user interface components

Application modules connect to all software layers as well as to the .NET framework. Application
modules can register their own services with the Ocean Core and benefit from services
registered by other modules. All applications built on the Ocean framework are designed in a
similar fashion, but they rely on a product family to build and run.

Access to the Petrel Data Domain


The application can access data in the following domains provided by Ocean for Petrel:

Analysis (for data analysis)

FaultModel (for fault modeling)

Stratigraphy (for stratigraphy)

Well (for Petrophysics and Geology applications)

Prestack, Seismic, SeismicGeobody (for Geophysics)

Shapes (for generic geometric objects)

FrameworkModeling (for Structural modeling)

PillarGrid, UnstructuredPillarGrid (for Geomodeling)

Simulation (for Reservoir Evaluation)

This is not an exhaustive list.

Figure 2: Surface with fault model and seismic data

Ocean for Petrel UI Infrastructure


Ocean provides the capability to extend Petrels user interface functionality. The Ocean for
Petrel Application Programming Interface (API) supports:

Windows:
o

Adding custom windows

Welcome to Ocean for Petrel

Renderers:
o

Adding renderers for domain objects (native and custom) in different windows

Interactions:
o

Adding custom window modes to define interactions in different windows

Object picking in different windows for its manipulation

Menus and toolbars:


o

Adding new menus to Petrel window or extending Petrel menus

Adding new toolbars with custom tools

Extending Petrel toolbars with custom tools

Petrel project explorer:


o

Adding custom objects in Petrel tree in a particular hierarchy

Adding processes and workflows in the Petrel process diagram and workflow
editor

This is not an exhaustive list.

The Ocean Plug-in and Module


An Ocean module is an extension to the product family. Plug-in programmers create modules
that behave just like any standard part of Petrel. The modules are compiled into assemblies.
Modules are combined in a plug-in that provides identity and support information. Plug-ins are
installed by the Petrel Plug-in Manager found under the Help menu of Petrel. The Plug-in
Manager reads a .pip (Plug-in Installation Package) file that is deployed for the plug-in and uses it
to define the plug-ins, and their modules, loaded when Petrel is started.
The following figure shows a sample Ocean plug-in with modules.

PLUG-IN

M odul e A
M odul e B
M odul e C

Figure 3: Ocean Modules

The Ocean module has a defined lifecycle with certain requirements and restrictions that allow
the clean integration into the product family. Its lifecycle phases serve to license the module,

Welcome to Ocean for Petrel

initialize and integrate it into the product family, add presentation interfaces, and remove all
these when the module is unloaded. The appearance and interaction is seamless and allows the
product family to treat the module as native code.
An Ocean module uses the functionalities provided by the product family, the Ocean Services,
the Ocean Core, and also the .NET architecture. It may also use third party application
assemblies and other modules.
Ocean for Petrel modules are built with Visual Studio 2011 or Visual Studio 2012 for .NET, with
the help of the Ocean for Petrel wizard. The wizard takes care of the interaction with the Core as
well as some low-level access to functionality provided by the Petrel product family.

Plugin class
An Ocean plugin derives from the abstract Plugin class, defined in the Slb.Ocean.Core
namespace. During Petrel startup, the Ocean Core will load plug-ins and their contained modules
as defined in the PluginManagerSettings.xml file. The Plugin class contains information about the
plug-in and its identity. The following is an example module:
using Slb.Ocean.Core;
using Slb.Ocean.Core;
public class MyPlugin : Plugin
{ ...
public override string Name { get { return "Plugin Demo"; } }
public override PluginIdentifier PluginId
{ get { return new PluginIdentifier("PluginDemo", new Version("1.0.0.0")); } }
public override IEnumerable<ModuleReference> Modules
{
get { yield return new ModuleReference(typeof(DemoModule));
yield return new ModuleReference(typeof(DemoModule2)); }
}
public override IEnumerable<PluginIdentifier> Dependencies
{ get { return new List<PluginIdentifier>(); } }
public override string Description { get { return "Example plug-in"; } }
public override string AppVersion { get { return "2013.0"; } }
public override string Author { get { return "Joe Smith"; } }
public override string ImageResourceName
{ get { return "MyPlugin.MyImage.bmp"; } } // used if Plugin is licensed
public override string DeploymentFolder
{ get { return "OceanTraining"; } }
}

IModule Interface
An Ocean module implements the IModule interface. IModule is defined in the Slb.Ocean.Core
namespace.
The IModule interface defines five methods of the module lifecycle phases and inherits from
IDisposable. The phases and their methods are:

Construction (default constructor)

Initialization (Initialize)

Integration (Integrate)

Welcome to Ocean for Petrel

Presentation integration (IntegratePresentation)

Disintegration (Disintegrate)

Disposal (Dispose)

During the product startup, the Ocean Core will load modules as defined in a configuration file
for the product family. The Ocean Core will call the default constructor to instantiate each
module. The constructor can be used to initialize any private fields, and acquire any resources
the module needs.
The second phase of the module lifecycle is the execution of the Initialize method. The main
purpose of Initialize is registration of the services provided by the module with the Ocean
ServiceLocator class. When initialization is complete the services registered are available for
consumption by all Ocean modules.
The Integrate method is the first point at which a module may consume services registered with
Ocean. This is because all modules have been through the initialize phase where their services
are registered with Ocean. The Ocean Core ServiceLocator class is used to look up services.
The IntegratePresentation method of IModule is the phase in the module lifecycle in which user
interface components (menus, toolbars, context menus, windows etc.) are added to the product
family.
When the product family begins to shut down, the IModule Disintegrate method is called on
each module. Disintegrate has the responsibility of cleaning up any presentation elements
installed by the module.
Dispose comes from the IDisposable pattern and must be implemented as part of the IModule
implementation. The purpose of Dispose is to free any unmanaged resources and free any
licenses acquired by the module.
The following is an example module:
using Slb.Ocean.Core;
using Slb.Ocean.Coordinates;
public class MyModule : IModule
{
// Perform initializations of private properties, resources.
public Module ()
{ ...

// Initialize services provided by the module


public Initialize ()
{
// Create the service
object FooBar = new FooBarService();
// Add the service by its type
CoreSystem.Services.AddService(typeof(FooBarService), FooBar);
...
}
// Integrate services provided by other modules
public Integrate ()
{
// Find the coordinate system service
ICoordinateService coordService;
coordService = CoreSystem.GetService<ICoordinateService>();
...

Welcome to Ocean for Petrel

}
// Add to user interface of product family
public IntegratePresentation ()
{
// Define the button to add
PetrelButtonTool btn = new PetrelButtonTool(MyButton,
PetrelImages.Cyan,
ButtonClick);
// Add the button to the Insert menu of the Petrel menubar
WellKnownMenus.Tools.AddTool(btn);
...
}
// Remove components added to the user interface. Remove services
public Disintegrate ()
{
// Remove the button added to the Insert menu
WellKnownMenus.Tools.RemoveTool(btn);
// Remove our service
CoreSystem.Services.RemoveService(typeof(FooBarService));
...
}
// Dispose of any unmanaged resources
public Dispose ()
{ ...

Writing Your
First Plug-In

WRITING YOUR
FIRST PLUG-IN
Ocean for Petrel allows application developers to extend the Petrel functionality with new
custom processes and workflows. This chapter describes the procedure of creating a simple
process.

Writing the Plug-in


In your first plug-in, you will write an Ocean plug-in with a module that adds a process to Petrel.
The process will print the names of all Seismic cubes in the current project.
A process in Petrel is an interactive operation performed on data. The process is available from
the Petrel process diagram. The operation could create new data or update existing data. For
example, the operation of using a set of points to create a well path would be referred to as a
process. In this example, the set of points is the input, and the well path is the output.
A workstep is a single processing step. It differs from a process in that it does not require manual
interaction when executing. This is why it can take part in a workflow. Worksteps are available
from the Petrel workflow editor; they also take input data and parameters, perform some
processing, and produce output data.
A process can be created from a workstep, so you can write code one time that is available in
both the process diagram and the workflow editor.
For your first plug-in, you will use the Ocean Wizard to create a process from a workstep.
There are three main steps for creating your first plug-in. Each step will be detailed in the
sections that follow. The steps are:

Run the Ocean for Petrel Wizard in Visual Studio to create the plug-in and module.

Inspect the files created by the Wizard.

Modify the code to add the processing logic.

For details on the installation and use of the Ocean Wizard, please refer to the appendix of this
document.
For details on processes and worksteps, please see the Workflow chapter in the Ocean
Developers Guide.

Creating the Plugin, Module and Process with Visual Studio


To create the project, plugin, module, process, and workstep using Visual Studio:
Start Visual Studio.
Create a new project by selecting File > New Project. In the Project types area, under Visual C#
project type, select Ocean. Then select the Ocean Plug-in template. Provide the name
ListSeismic for the project. Click the OK button to start the Wizard. (See Figure 4.)

10

Writing Your
First Plug-In

Ocean

Ocean Plugin

Project

template

type

Ocean
Projects
Type
Project name

Figure 4: New Project Window

It is generally a good practice to use a descriptive plug-in name. Change the name of your plug-in
to ListSeismicPlugin. Change the Author, Contact, Plugin URL, and Description fields as
appropriate. Also, since we are adding a module to the plug-in turn on the Create new module
and the Register existing modules checkboxes (See Figure 5.). Click Next in the dialog.

11

Writing Your
First Plug-In
Figure 5: Plug-in Creation step 1 window

The wizard will create the name of the module from the namespace with .Module appended.
Review the content (see Figure 6) and click Next in the dialog.

Figure 6: Plug-in Creation step 2 window

It is generally a good practice to use the name Module for the application module. Change the
name of your module to ListSeismicModule. Create a workstep in your module by checking
the New Workstep box; give it the name ListSeismicCubes. Click the Next button. (See Figure
7.)

12

Writing Your
First Plug-In

Module name

Workstep
name

Figure 7: Ocean Module Project options

For your workstep, enter a Short description of My First Ocean Process and a Long description
of This process will print the names of all seismic cubes in the current project. Ensure that
Generate custom UI is unchecked in order to use the default UI automatically generated by
Ocean. This workstep should have its own process wrapper; ensure that Generate process
wrapper is checked. Click the Next button. (See Figure 8.)

13

Writing Your
First Plug-In

Figure 8: Ocean Workstep Details

Do not specify any workstep arguments; they are not needed. Click the Next button. (See
Figure 9.)

Figure 9: Ocean Workstep Argument Details

Review what the wizard will generate and click the Finish button. (See Figure 10.)

14

Writing Your
First Plug-In

Figure 10: Ocean for Petrel Module Project settings

Inspecting the Files


The Ocean for Petrel Module Wizard will create a solution named ListSeismic with a project
named ListSeismic in the Visual Studio Solution Explorer. The project will contain source files
for the Plugin class that was created, the Module class that was created, as well as the
ListSeismicCubes process that is added to the Process diagram. (See 11.)

Figure 11: Example Project Source Files in Solution Explorer

The Wizard configures the ListSeismic project to make debugging simple. The assembly is output
to the Petrel installation directory. The project command line property is set up to start Petrel.
So debugging is simply a matter of building and starting the debugger.
The Wizard writes the basic code needed for the ListSeismicCubes plug-in. You will need to add
code for your specialized algorithm in order to print the names of all Seismic Cubes in the
current project.

15

Writing Your
First Plug-In

Plugin
The Plugin class contains properties which provide identity to the plugin and is generated by the
wizard from the values you entered and the Ocean version. Thes include AppVersion, Author,
Contact, Dependencies, Description, ImageResourceName, PluginUri, Modules, Name,
PluginId, and Trust.
Pl

Module
The Module class implements the IModule interface. The new process is added to the Process
manager in the Integrate method automatically by the Wizard.
T

First the new ListSeismicCubes workstep is created, and then it is added to the Workflow editor.
Finally, the process is created from the workstep using the WorkstepProcessWrapper
convenience class. The new process is added to the process diagram using the
PetrelSystem.ProcessDiagram API. Putting the pieces together, the Wizard generated the
following Integrate method:
T

public void Integrate()


{
ListSeismicCubes listseismiccubesInstance = new ListSeismicCubes();
PetrelSystem.WorkflowEditor.Add(listseismiccubesInstance);
PetrelSystem.ProcessDiagram.Add(new WorkstepProcessWrapper(
listseismiccubesInstance),"Plug-ins");
}

ListSeismicCubes
The ListSeismicCubes class is the workstep class that holds the processing algorithm. Previously,
you saw how a process was created from it in the module.
T

ListSeismicCubes derives from Workstep<> , a generic class that includes the definition of the
arguments. The wizard implements much of the class for you, including the argument creation
and copy methods. Arguments creation is very basic. Arguments copy can be done with the
DescribedArgumentsHelper static class.
T

The Wizard also implements two interfaces, IAppearance (for its appearance in the Process
diagram) and IDescriptionSource (to display information in the Process UI). We do not need the
setters for Text and Image properties, so you may delete them.
T

ListSeismicCubes also contains an Arguments class created by the Wizard, which in this case is
empty since the algorithm has no arguments.
T

Writing the Algorithm Code


The Wizard wrote nearly all of the ListSeismicCubes class except for the custom algorithm code.
It implemented the IExecutorSource interface and an instance of the Executor class. You will add
the custom algorithm code to the ExecuteSimple method, which will be called when the
workstep or process is executed.
T

public class ListSeismicCubes :

Workstep<ListSeismicCubes.Arguments>,

IExecutorSource, IAppearance, IDescriptionSource


{
#region IExecutorSource Members and Executor class

16

Writing Your
First Plug-In
public Slb.Ocean.Petrel.Workflow.Executor GetExecutor
( object argumentPackage, WorkflowRuntimeContext ctx )
{
return new Executor ( argumentPackage as Arguments, ctx );
}
public class Executor : Slb.Ocean.Petrel.Workflow.Executor
{
Arguments arguments;
WorkflowRuntimeContext context;
public Executor ( Arguments arguments, WorkflowRuntimeContext ctx )
{
this.arguments = arguments;
this.context = ctx;
}
public override void ExecuteSimple( )
{
// TODO: Implement the workstep logic here.
}
#endregion
...
}

To write the algorithm code:


Access the APIs from the Seismic namespace by adding a reference in your project to the
Slb.Ocean.Data.dll, Slb.Ocean.Petrel.DomainObject.dll and to the Slb.Ocean.Petrel.Seismic.dll.
You must also add a reference to Slb.Ocean.Petrel.Basics.dll. These assemblies are available in
the Public folder of the Petrel installation directory.
Add the following using statements for the required namespaces at the top with the other using
statements.
using System.Collections.Generic;
using Slb.Ocean.Petrel.DomainObject;
using Slb.Ocean.Petrel.DomainObject.Seismic;

Code the ExecuteSimple method. The work for the process is completed as follows:
Read the current project using the PetrelProject.PrimaryProject API. Use the static class
SeismicRoot to find the root of all domain objects in the seismic domain. It exposes a property
SeismicProject, which provides navigation to all seismic collections and interpretation
collections in the project. Parse through all the seismic collections and print the names of all
seismic cubes within them using the InfoOutputWindow method of the PetrelLogger class. Build
a dynamic list of surveys (SeismicCollection) to avoid recursive calls while providing a breadth
traversal of the survey tree. The PetrelLogger static convenience class provides static methods
to show a textual display of information to users. The InfoOutputWindow is used to issue an
information message that is intended for all end users to see, but without being highly
interruptive.
T

The following shows the complete Executor class:


using Slb.Ocean.Petrel.DomainObject;
public class Executor : Slb.Ocean.Petrel.Workflow.Executor
{
Arguments arguments;
WorkflowRuntimeContext context;
public Executor ( Arguments arguments, WorkflowRuntimeContext context )

17

Writing Your
First Plug-In
{
this.arguments = arguments;
this.context = context;
}
public override void ExecuteSimple( )
{
// Get current primary project
Project proj =

PetrelProject.PrimaryProject;

// Get the root of all domain objects in the seismic domain


SeismicRoot root = SeismicRoot.Get(proj);
SeismicProject sProj = root.SeismicProject;
// Find all seismic collections in the current project
IEnumerable<SeismicCollection> col = sProj.SeismicCollections;
List<SeismicCollection> listCol;
listCol = new List<SeismicCollection>(col);
for(int idx = 0; idx < listCol.Count; idx++)
{
SeismicCollection curr = listCol[idx];
foreach (SeismicCollection sCol in curr.SeismicCollections)
{
listCol.Add(sCol);
}
// Find all Seismic cubes in the current collection
foreach (SeismicCube cube in curr.SeismicCubes)
{
PetrelLogger.InfoOutputWindow(curr.Name +
" contains Seismic Cube " + cube.Name);
}
}
return;
}
}

Running the Plug-in


You have just completed the modification of the ExecuteSimple method. In this section, you will
finish building the solution and run Petrel with your plug-in.
T

Build your solution in Visual Studio. This will create the assembly for the plug-in. It will also
create a plugin.xml file and merge its contents into the PluginManagerSettings.xml file. The
PluginManagerSettings.xml file exists under your %AppData% directory for your account on your
PC. Typically this is C:\Users\<username>\AppData\Roaming\Schlumberger\Petrel\2013\. This
file is used when Petrel is started to define the plug-ins, and their associated modules, which will
be loaded by the Plugin Manager.
Start Petrel.
In Petrel, open the demo project deployed with the Ocean SDK. Then go to the Process diagram
window and find ListSeismicCubes (12).

18

Writing Your
First Plug-In

Figure 12: ListSeismicCubes Selected in Process Diagram

Double click ListSeismicCubes to start the process and display the ListSeismicCubes dialog.
The short and long descriptions are shown in the top section of the dialog. There are no
arguments for the process, so the lower section is empty, as shown in the following figure.

Figure 13: ListSeismicCubes Dialog

Click Apply to run the process. The ListSeismicCubes process will show the seismic cubes in the
Petrel message log (Figure 14).

Figure 14: ListSeismicCubes Output Messages

19

Writing Your
First Plug-In

Exit Petrel.
You have now written, built, and run your first Ocean plug-in. You can find further details about
the Ocean Wizard and the functionality it offers in the Appendix of this document.

Using the Online Help


As you explore the Ocean APIs in the upcoming sections and in your development, you will want
to look at the online documentation. The Ocean SDK includes online help exposing all the
namespaces, classes, and interfaces implemented in the API.

Opening the Online Help


Ocean help should be integrated into Visual Studio Help and into F1 help when the Ocean SDK is
installed. To select the online help, open Visual Studio, and select View Help from the Help
menu as shown:

Hit F1 on a class, interface, property, method or other part of the Ocean API while you are in the
Visual Studio editor window to bring up the corresponding help in a browser window, like you
can for Microsoft APIs.
You can open the Ocean.chm file directly from the Documentation folder of the Ocean SDK
installation directory or from the Ocean Start Page in Visual Studio.

Using IntelliSense
In Visual Studio, the Ocean library references (files with .dll extensions) allow the environment
to select class members and methods from a list that is dynamically generated from the types of
the variables in the code. This feature helps you select the correct class syntax without having to
explicitly search for information in the Ocean help.

20

Writing Your
First Plug-In

Accessing Class Definitions


While editing code, you can go directly to the class definition of the current variable declaration.
To do this, right-click on the class name, and Visual Studio opens the class reference menu as
shown in the following figure.

Select Go To Definition. The following editor opens in your Visual Studio environment.

21

Understanding the Petrel Data Domain

UNDERSTANDING THE PETREL DATA


DOMAIN
Exposing Petrels Data Model
Ocean for Petrel accesses data stored in Petrel Projects. The types of data that Ocean may
access increase with each release as Petrels data model expands and as more of the data is
exposed through Ocean for Petrel. The Ocean for Petrel API documentation that accompanies
the release contains the definitions of all exposed data types, their properties, and methods for
access.
This section will help you understand the Petrel data domain as it relates to developing
applications. Sample code is included to assist you in learning to use the API.
However, this document is only intended to help you get started using the Ocean for Petrel API,
and not every feature or every domain is covered here. For a complete discussion of the Ocean
for Petrel features, functionality and usage, refer to the Ocean Developers Guide.

Entities and Properties


A project built by Petrel contains data elements that represent earth entities (a well, a surface, a
reservoir). These entities are characterized by properties (such as logs along a well bore, height
fields across a surface, or porosity distributions in a reservoir). Both types of data are exposed in
Ocean by classes, called domain objects.
The entity instance carries the geometry of the object it represents. The property object only
carries property values.

Templates
Each property object in Ocean has a template associated with it so that the application working
with it has a way to determine how to display the property values. The template defines the
units, scale, and color table used by the object. The templates are found in the
PetrelProject.WellKnownTemplates.

User View of the Petrel Data Model


The Petrel Project organizes the users view of the project in different trees:

22

Input

Models

Results

Cases

Templates

Understanding the Petrel Data Domain

Processes

All the trees are accessible via the API. Data is organized in pseudo-folders, seen in the API as
object collections. Each view is described in the following sections.

Input Data

Figure 15: Input Data Tree

The Input Data function gathers all data that is needed to build a static model. This includes all
data acquired and processed (well logs, geological markers, seismic data sets, seismic attributes)
and all data that is interpreted from the field measurements (petrophysical properties, seismic
time interpretations, velocity functions).
Most domain objects visible in the Input data tree are accessible in Ocean from the following
specialized collections:
BoreholeCollection This collection class contains boreholes, logs, and completions, as well as
nested BoreholeCollections. See the Well data model for details.
MarkerCollection This is the geology data model. These collections contain markers, horizons,
zones, and fluid contacts.
SeismicCollection This collection is for 3D and 2D seismic collections.
InterpretationCollection This collection is for all seismic interpretation.
Collection Other folders are accessible as generic collections. From these collections, the API
can access point sets, polyline sets, and surfaces.

23

Understanding the Petrel Data Domain

Models

Figure 5: Models Data Tree

The Models data tree includes all elements of the pillar grid static model and the property
objects that represent property distributions throughout the pillar grid cell array.
Domain objects visible in the Models data tree are accessible from the following collections:
ModelCollection. This top level container in the Models tree enumerates all the Models (pillar
grids) in the tree. Model collections are not nested.
Grid.PropertyCollection. Specific to each model, the collection lists all property and fault
property instances in that model.
Fault.Properties. This collection lists all fault properties, per fault, in a pillar grid model.

24

Understanding the Petrel Data Domain

Results

Figure 6: Results Tree

Results are simulation results imported back in Petrel to compare the static models with their
possible evolution through time. They are available as CaseResults from the simulation Case.
You can then get all SummaryTimeSeries and GridPropertyTimeSeries or the ones
corresponding to a given SummaryResult or GridResult.

Cases

Figure 7: Cases Tree

The Cases tree exposes simulation cases based on different hypotheses but also represents
various interpretation versions driving static model property variations. You can access Case,
AnalysisCase, and CalculationCase instances from SimulationRoot. There is currently no
hierarchy in the Ocean API.
25

Understanding the Petrel Data Domain

Templates

Figure 8: Templates Tree

The Templates tree exposes templates that are used by the Petrel user to define the data type
for the domain objects in the project. The templates are not domain specific. This means that
the Porosity template may be used to represent data for a Porosity well log as well as a Porosity
property of a pillar grid.

Processes

Figure 9: Processes Tree

The Processes tree exposes the Petrel processes used by the Petrel user to perform various
actions on data. The processes are interactive in nature in that activating one causes the process
toolbar on the right side of the Petrel UI to update to indicate the tools that are available to the
process.

26

Understanding the Petrel Data Domain

Data Access
The Ocean for Petrel API offers the following data access types:
Read: The API reads existing data, browsing through data folders, enumerating collection
contents and following the parent-child relationships.
Update: The API updates existing objects, modifying entity characteristics (such as its geometry)
and modifying property values (like correcting log values in chosen points).
Create: The API creates new instances of Petrel object classes, augmenting the project with new
data the same way Petrel applications do.
Delete: The API deletes objects that are no longer needed in the project.

Common Exposed Data Types


Details are given in the compiled html manual part of the Ocean SDK release, Ocean.chm in the
Documentation subdirectory.

Seismic
Ocean classes for Seismic are found in namespace Slb.Ocean.Petrel.DomainObject.Seismic. You
can access virtual cubes and virtual 2D data via class SeismicAttribute.

Well
Ocean classes for well data are found in namespace Slb.Ocean.Petrel.DomainObject.Well.
Different types of Logs are available: property valued well logs, facies well logs, point logs,
multitrace well logs, bitmap well logs, comment well logs, and borehole seismograms. Also
available in the Well namespace are completions and observed data.

Geology
Ocean classes for well marker data, sometimes referred to as well tops, are found in namespace
Slb.Ocean.Petrel.DomainObject.Well.
You can create stratigraphy columns across a number of wells. Fault and interface-type surfaces
are just named references.

Shapes
Ocean classes for objects defining various shapes are found in the namespace
Slb.Ocean.Petrel.DomainObject.Shapes.
You can add properties to point sets, surfaces, and polyline sets. Surfaces can be irregular or
gridded (regular height field), though only regular height field surfaces can be created. Both can
be assigned property values.

27

Understanding the Petrel Data Domain

Pillar Grid
Ocean classes for pillar grids and their related objects are found in the namespace
Slb.Ocean.Petrel.DomainObject.PillarGrid.
Pillar grid property retains some knowledge of statistical treatment completed at creation time,
including which cells have been upscaled as well as statistical distributions of facies values.

Simulation
Ocean classes for simulation cases and simulation results are found in namespace
Slb.Ocean.Petrel.DomainObject.Simulation.
A simulation case has a number of case runs, each providing time series (results vs time) data for
combinations of result categories (fields, wells) and result properties (oil production, water flow
rate, etc.).
Streamlines can be added to various stream line sets in a simulation case. Property values can
also be read and appended and new property types added.

Read Access
Browsing Collections
There is no query service implemented on the Petrel Project as it is not implemented in a
relational database. Instead, data browsing is done by following the non-taxonomic hierarchy. At
the top level of each domain is a root object which gives you access to all of the data in that
domain. It is possible to browse through the whole data domain of a project by starting from the
different root objects.
Root objects offer access to collections, which may be nested. From each collection, the API can
access the entities and the properties that are relevant to that collection type.

Seismic Data

Seismic data is rooted in the projects SeismicProject instance (which is a singleton) once it has
been created. It is accessed, if it exists, from the SeismicRoot of the project. It only exists if
seismic data are included in the project.
Below the SeismicProject are two separate hierarchies in the Seismic domain, one for seismic

28

Understanding the Petrel Data Domain

data with nested SeismicCollection objects, the other for interpretation picks with a nested
hierarchy of InterpretationCollection instances.
Project proj = PetrelProject.PrimaryProject;
SeismicRoot sr = SeismicRoot.Get(proj);
SeismicProject sp = sr.GetOrCreateSeismicProject();
// navigate the Seismic data hierarchy
foreach (SeismicCollection scol in sp.SeismicCollections)
{

... }

// navigate the Seismic interpretation hierarchy


foreach(InterpretationCollection icol in sp.InterpretationCollections)
{

... }

Seismic data in a SeismicCollection include either seismic cubes or seismic 2D surveys


(collections of lines).
Interpretation data include HorizonInterpretation or FaultInterpretation instances each
including 3D and 2D time picks that can be accessed separately.

Well and Geology

Wells belong to a nested hierarchy of BoreholeCollection objects that contain boreholes,


trajectories, and logs. Markers are stored under stratigraphic columns or under horizon, zone,
and marker collections. You can find lists of such collections at the top level, implemented in the
API by the MarkerCollection class.
Your application can access all well and geology objects at the root of the project from the
WellRoot class. WellRoot is unique for the project and retrieved from a static method in the
WellRoot class as shown in the following.
Project proj = PetrelProject.PrimaryProject;
WellRoot wr = WellRoot.Get(proj);
// Get top level Borehole Collection
BoreholeCollection bhcol = wr.BoreholeCollections;
...

Once the WellRoot instance is retrieved by the system, it gives access to borehole and marker

29

Understanding the Petrel Data Domain

collections.
public sealed class WellRoot : ...
{

...
public BoreholeCollection BoreholeCollection { get; }
public int WellLogVersionCount { get; }
public IEnumerable<PropertyVersion> WellLogVersions { get; }
public int MarkerCollectionCount { get; }
public IEnumerable<MarkerCollection> MarkerCollections { get; }

Boreholes are in nested collections, rooted at the top level collection retrieved from WellRoot.
Marker collections are not nested. Lists of collections, each corresponding to a different
stratigraphic classification, are at the top level.

Pillar Grid Model

Pillar grids are in a hierarchy that contains the property hierarchies. Hierarchy retrieval starts
from the PillarGridRoot object.
PillarGridRoot grid = PillarGridRoot.Get(proj);
IEnumerable<ModelCollection> mcolls;
mcolls = ModelCollection.GetRootModelCollections(proj);
foreach (ModelCollection mcol in mcolls)
{
foreach (Grid g in gr.GetGrids(mcol)
{ ... }
}

Each Grid object interfaces a full static model with intersecting horizons and pillar-based faults.
Grid g = ...
foreach (Fault f in g.Faults)
{ ... }
foreach (Horizon hor in g.Horizons)
{ ... }

The model is populated by property values that are accessed in a nested hierarchy of
PropertyCollection folders.
Grid g = ...
PropertyCollection pcol = g.PropertyCollection;
foreach (Property prop in pcol.Properties)
{

30

Understanding the Petrel Data Domain

Template template = prop.Template;


// recurse on subcollections
foreach (PropertyCollection subcol in pcol.PropertyCollections)
{ ...

Simulation and Data Analysis

Simulation cases, result properties, and result hierarchies belong to separate hierarchies. The
time series are defined by combinations of these.
Simulation case runs are retrieved from SimulationRoot. The simulation case gives access to
simulation results and streamlines. For time series, the result property and category must be
supplied by the application.
SimulationRoot root = ...
foreach (Case case in root.Cases)
{
StreamlineSet sls = case.StreamlineSet;
if (sls != StreamlineSet.NullObject)
foreach (StreamlineSubset sub in sls.StreamlineSubsets)
foreach (Streamline sl in sub.Streamlines)
{ ... }
}

Updating Data
Your application can update data by modifying the object that is seen through the API. Updating
an entity or a property object alters the project. After updating the project, you must decide
whether to save the project changes or not. From the API standpoint, however, the project has
been modified as soon as an object has been edited.
You must make any such updates inside a transaction and any modified object must be locked
beforehand inside that transaction.

Using Transactions
A transaction represents a group of edits made to data (domain objects). Transactions are
required for operations on native Petrel domain objects that will change the data: create,

31

Understanding the Petrel Data Domain

update, and delete.


Transactions use the Slb.Ocean.Core.ITransaction interface. To use a transaction:

Create a transaction.

Lock domain objects that are going to be changed.

Modify the domain objects.

Commit the transaction.

Dispose of the created transaction.

In Petrel, transactions are used to batch event notifications. Petrel does not use a data base, so
changes to domain objects made within a transaction happen immediately.

Modifying Domain Objects


You can modify a domain object in the transaction after it has been locked. The online Ocean
documentation will indicate which object property can be modified.
The nature of the class members is also explicitly shown in the class definitions that are
accessible from the Visual Studio environment.
namespace Slb.Ocean.Petrel.DomainObject.Well
{
public sealed class WellLog : ...
{
public Borehole Borehole { get; }
public string Comments { get; set; }
public int SampleCount { get; }
public IEnumerable<WellLogSample> Samples { get; set; }
...
}
}

The array of log values, Samples, is read-write but SampleCount is read-only (dynamically
evaluated from the array size).

Accessing Domain Object Relationships


You can access object-to-object relationships via the API. For these relationships to be
modifiable, the corresponding class property must allow write access, which is, as a general rule,
not the case as parts-of relationships impose constraints between parent and child. For instance
a pillar grid Property cannot be separated from the Grid object that defines its geometry. Even
when you modify the containment hierarchy interactively, the API often makes the
corresponding relationship immutable.
However, there are cases where it makes sense to allow write access to parts-of relations. This is
the case when object creation does not require such a relationship to be established. For
instance, it is possible to update the reference from a marker to a given surface (fault or
horizon).
The example below clears the stratigraphic references of a set of markers in a given borehole.
MarkerCollection mcol = ...
Borehole bh = ...
Horizon hor = Horizon.NullObject;

32

Understanding the Petrel Data Domain

foreach (Marker m in mcol.GetMarkers(bh))


{ m.Surface = hor; }

Refer to the online help to determine whether a relationship is read-only.

Domain Object Creation


Creating New Instances

Most objects accessible via the API can be instantiated. However, the API never allows class
instantiation in the classical manner. API classes are sealed, and some objects are even exposed
simply as interfaces. To create a new class instance, the API has specialized Create methods.

Using Transactions
The plug-in code must create domain objects inside transactions, just like object updates.
However, an object creation modifies its parent entity (in the non-taxonomic hierarchy) or the
collection of similar entities that will harbor it. That parent or collection has to be locked in the
transaction.
You can modify the newly created object until the transaction commits. It is locked by default,
only its parent had to be locked explicitly in the transaction.

Locating the Correct Create Method


The Create method is always located in the class of the containing object. Borehole contains
WellLog collections where the Create method for logs can be found.
using (ITransaction t = DataManager.NewTransaction())
{
Template template = ...
WellRoot wr = WellRoot.Get(PetrelProject.PrimaryProject);
LogVersionCollection rootLVCol = wr.LogVersionCollection;
t.Lock(rootLVCol);
WellLogVersion version = rootLVCol.CreateWellLogVersion(Gamma, template);
Borehole bh = ...
t.Lock(bh);

33

Understanding the Petrel Data Domain

WellLog wl = bh.Logs.CreateWellLog(version);
...
}

Creating New Collections


When it does not make sense to create an entity in a predefined collection, you must create a
new collection. Collections are often nested, so adding a collection is adding a branch to a tree.
Classes that model nested collections allow creation of sub-collections. For example a
PropertyCollection can contain sub-collections and would carry a Create method for branching
out at that point.
ITransaction t = ...
PropertyCollection pcol = ...
t.Lock(pcol);
string colName = "New Sub-Collection";
PropertyCollection subcol = pcol.CreatePropertyCollection(colName);
t.Commit();
t.Dispose();

New Top-Level Collections


For top-level objects (like collections) the Create methods are in static classes. For example, the
top level collection for Seismic data is created in the SeismicProject instance.
There are few collections that can appear at the top level of Petrel data trees. Nested collections
are rooted under a top level collection that is only created once. Un-nested collections that can
be added at the root of Input or Models data trees include the following:

MarkerCollection

ModelCollection

Collection

These collections are created directly from the Petrel primary Project or the WellRoot object.
ITransaction t = ...
Project proj = PetrelProject.PrimaryProject;
WellRoot root = WellRoot.Get(proj);
t.Lock(proj);
proj.CreateModelCollection("New Pillar Model");
t.Lock(root);
root.CreateMarkerCollection("New Stratigraphic Model");
t.Commit();
t.Dispose();

Nested Collections
Collections that are always grouped under a root collection are created using a specific
container, WellRoot for boreholes and SeismicProject for seismic data and interpretation. These
are used for the following nested collections:

34

SeismicCollection

InterpretationCollection

Understanding the Petrel Data Domain

BoreholeCollection

There is no specific object at the root of all borehole collections, instead there is a generic
BoreholeCollection called Wells that you can only create once.
ITransaction t = ...
Project proj = PetrelProject.PrimaryProject;
SeismicRoot root = SeismicRoot.Get(proj);
SeismicProject sproj = root.SeismicProject;
WellRoot wroot = WellRoot.Get(proj);
t.Lock(sproj);
string colName = "New Collection";
SeismicCollection scol = sproj.CreateSeismicCollection(colName);
String iName = New Interpretation);
InterpretationCollection icol;
icol = sproj.CreateInterpretationCollection(iName);
...
t.Lock(wroot);
BoreholeCollection bcol = wroot. GetOrCreateBoreholeCollection();
...

You can also create collections that are placed under an object container, for example, under the
PillarGrid.
ITransaction t = ...
Grid g = ...
t.Lock(g);
PropertyCollection root = g.PropertyCollection;
String colName = New Properties;
PropertyCollection sub = root.CreatePropertyCollection(colName);
...

Deleting Objects
Deletion of an existing instance is done by calling the Delete method on the object itself.
Deletion is always done inside a transaction and the object to be deleted must be locked first.

Accessing Data: Examples


In the following example you will browse through wells in the project, retrieve a porosity log,
browse through static models, and create a new Property for the latest modified model in the
project.
The created property will be filled with values extracted from the well log in cells where actual
log measurements exist.

35

Understanding the Petrel Data Domain

Browsing Well Logs


Use the following code to browse well logs to find a porosity measurement.
Project proj = PetrelProject.PrimaryProject;
WellRoot root = WellRoot.Get(proj);
BoreholeCollection wells = root.BoreholeCollection;
WellLog poro = WellLog.NullObject;
ITemplate template = PetrelProject.WellKnownTemplates.PetrophysicalGroup.Porosity;
IUnitMeasurement um = template.UnitMeasurement;
foreach (BoreholeCollection bhc in wells.BoreholeCollections)
{
foreach (Borehole bh in bhc)
{
foreach (WellLog l in bh.Logs.WellLogs)
{
if (l.WellLogVersion.UnitMeasurement.Equals(um))
{
poro = l;
break;
}
}
if (!poro.IsGood) break;
}
if (!poro.IsGood) break;
}
if (poro == WellLog.NullObject) return;
PetrelLogger.InfoOutputWindow("Found log " + poro.Name);

Retrieving Models
To retrieve the latest model:
Grid latest = Grid.NullObject;
DateTime last = new DateTime(1980, 1, 1);
PillarGridRoot proot = PillarGridRoot.Get(proj);

36

Understanding the Petrel Data Domain

foreach (Grid g in proot.Grids)


{
if (g.LastModified.Time.CompareTo(last) >= 0)
{
latest = g;
last = latest.LastModified.Time;
}
}
if (latest == Grid.NullObject) return;
PetrelLogger.InfoOutputWindow("Found grid " + latest.Name);

Creating New Property Collections


To create a new property collection in the model:
ITransaction t = DataManager.NewTransaction();
PropertyCollection pcol = latest.PropertyCollection;
t.Lock(pcol);
string Name = New Collection;
PropertyCollection newcol = pcol.CreatePropertyCollection(Name);

Creating the Pillar Grid Property


To create the pillar grid property:
t.Lock(newcol);
Property prop = newcol.CreateProperty(template);

Filling Values
To fill values:
IPillarGridIntersectionService ipgs;
ipgs = CoreSystem.GetService<IPillarGridIntersectionService>();
IPolyline3 traj = poro.Borehole.Trajectory.Polyline;
IEnumerable<SegmentCellIntersection> cells;
cells = ipgs.GetPillarGridPolylineIntersections(latest, traj);
foreach (SegmentCellIntersection cell in cells)
{
Index3 ijk = cell.EnteringCell;
Point3 xyz = cell.IntersectionPoint;
double index = poro.Borehole.Transform(Domain.ELEVATION_DEPTH,
xyz.Z, Domain.INDEX);
WellLogSample[] sam = new WellLogSample[](poro.Samples);
latest[ijk] = sam[(int)index];
}
t.Commit();
t.Dispose();

37

Extending the Petrel UI

EXTENDING THE PETREL UI


Ocean allows application developers to customize and extend the Petrel application UI. In this
chapter, you will explore a very simple customization: adding your own menu item to an existing
Petrel menu.
However, this document is only intended to help you get started using the Ocean for Petrel API,
and not every feature is covered here. For a complete discussion of the Ocean for Petrel
features, functionality and usage, refer to the Ocean Developers Guide.

Adding a New Menu Item


To create a new menu item:

Edit your modules IntegratePresentation method.

Use the Ocean convenience class PetrelMenuItem to create the menu item.

Add the menu item to the Petrel UI using the Ocean class PetrelSystem.ToolService.

Editing the IntegratePresentation Method


Use the following code example to add your new menu item in the modules
IntegratePresentation method:
public void IntegratePresentation ()
{
// add your new menu item here
}

Creating UI Tools
A tool is an item that appears on menus and toolbars. When a tool appears on a menu as a
menu item, it is drawn as a list entry with text as well as an optional image as shown in the
following example.
tool in menu, no image

tool in toolbar
Figure 10: Tools in Petrel UI

Ocean provides a set of convenience classes that extend the PetrelTool class to create tools such

38

Extending the Petrel UI

as a menu item.
public class PetrelMenuItem : PetrelTool, ...
{ ...
public PetrelMenuItem( string txt );
public PetrelMenuItem( string txt, Bitmap image );
}

To create an instance of the PetrelMenuItem convenience class:


PetrelMenuItem myListSeismic = new PetrelMenuItem( );

Defining the Menu Item Properties


You control the basic properties of the new menu item. You must specify text and UI location.
You can set these specifications in the PetrelMenuItem constructor, or you can set them later
using the PetrelTool properties.
public class PetrelTool : ..., IAppearance, IDisposable
{ ...
public string

Text

public System.Drawing.Bitmap Image

{ set; get; }
{ set; get; }

public event System.EventHandler Click;


}

You can also optionally provide an image and an event handler for a menu click.

Text
To supply the text to be shown in the menu item:
myListSeismic.Text = "List Seismic Cubes";

UI Location
To specify the UI location of the new menu item, you need to specify the menu to which it will
be added. In this case, the location is an existing Petrel menu as shown below.

Figure 11: Standard Petrel Menu

The Ocean WellKnownMenus static convenience class has a public static PetrelMenuItem field
for each existing Petrel menu.
public static class WellKnownMenus
{
public static PetrelMenuItem File

{ get; }

public static PetrelMenuItem Edit

{ get; }

public static PetrelMenuItem View

{ get; }

public static PetrelMenuItem Insert

{ get; }

public static PetrelMenuItem Project

{ get; }

public static PetrelMenuItem Tools

{ get; }

public static PetrelMenuItem Window

{ get; }

public static PetrelMenuItem Help

{ get; }

This new menu item should be placed in the Tools menu, so you should specify the Tools field.
39

Extending the Petrel UI

Image
You also have the option to set the image for the menu item. You can use an image from Petrel
that is available from the static class PetrelImages, or you can provide your own.
myListSeismic.Image = PetrelImages.Seismic3D;

Click Event Handler


Finally you need to specify what is going to happen when the menu item is clicked. For this
example, the menu item will run the same algorithm that you wrote for your workstep.
To specify the action, add a click handler to the menu item instance:
myListSeismic.Click += myListSeismicToolClick;

The click event handler is a System.EventHandler as shown in the following example:


using Slb.Ocean.Petrel.DomainObject;
using Slb.Ocean.Petrel.DomainObject.Seismic;
private void myListSeismicToolClick(object sender, EventArgs e)
{
Project project = PetrelProject.PrimaryProject;
SeismicRoot seismicRoot = SeismicRoot.Get(project);
SeismicProject seismicProj = seismicRoot.SeismicProject;
foreach(SeismicCollection scol in seismicProj.SeismicCollections)
{
if (scol.SeismicCubeCount > 0)
{
foreach (SeismicCube cube in scol.SeismicCubes)
PetrelLogger.InfoOutputWindow(scol.Name + " contains Seismic Cube "
+ cube.Name);
}
}
}

Adding the Item to the Menu


At this point, you have defined the new menu item (text, image, location, and what will happen
when the tool is clicked), but it is not a part of the Petrel user interface yet.
The PetrelMenuItem class provides functionality to add menu items. Use the AddTool method
to add the new menu item into the Petrel UI. The WellKnownMenus class properties that define
the menus in the Petrel menu bar are PetrelMenuItem objects.
public class PetrelMenuItem : PetrelTool
{ ...
public void AddTool ( IEnumerable<PetrelTool> tool );
public void AddTool ( params PetrelTool[] tools );
}

You will add the new tool to the UI after the tool is created:
WellKnownMenus.Tools.AddTool(myListSeismic);

40

Extending the Petrel UI

Viewing the Results


The following example shows the entire process of adding a new menu item into the Petrel Tools
menu:
public void IntegratePresentation ()
{
PetrelMenuItem myListSeismic = new PetrelMenuItem( );
myListSeismic.Text = "List Seismic Cubes";
myListSeismic.Image = PetrelImages.Seismic3D;
myListSeismic.Click += myListSeismicToolClick;
WellKnownMenus.Tools.AddTool(myListSeismic);
}

void myListSeismicToolClick(object sender, EventArgs e)


{
Project project = PetrelProject.PrimaryProject;
SeismicRoot seismicRoot = SeismicRoot.Get(project);
SeismicProject seisProj = seismicRoot.SeismicProject;
foreach(SeismicCollection scol in seisProj.SeismicCollections)
{
if (scol.SeismicCubeCount > 0)
{
foreach (SeismicCube cube in scol.SeismicCubes)
{
PetrelLogger.InfoOutputWindow(scol.Name +
" contains Seismic Cube " + cube.Name);
}
}
}
}

Now, after you rebuild your module and run Petrel, you will see a new menu item called List
Seismic Cubes in the Petrel Tools menu:

Figure 12: New List Seismic Cubes Menu Item in Petrel Tools Menu

41

Extending the Data Domain

EXTENDING THE DATA DOMAIN


Ocean for Petrel allows you to customize and extend the Petrel application by creating new data
objects, called custom domain objects. Custom domain objects can contribute implementations
for, and participate in, standard Petrel behavior. They can be added to the Input and Model
trees, or they can be displayed in a standard Petrel window.
You can decide what functionality to implement for a given custom domain object by deciding
what interfaces (services) to implement and register with Ocean for Petrel. All are optional in
terms of Ocean requirements.
This chapter briefly describes how to write a simple custom domain object and have it
participate in standard Petrel behavior.
However, this document is only intended to help you get started using the Ocean for Petrel API,
and not every feature is covered here. For a complete discussion of the Ocean for Petrel
features, functionality and usage, refer to the Ocean Developers Guide.

Basic Custom Domain Object


A custom domain object in Petrel is just a new class. The most basic custom domain object is a
class that inherits from the .NET object, even when it does not implement any Ocean interfaces.
Consider a simple object that has a position in space and a radius that defines its size.
public class XYZObj
{
private float m_x = 100.0f;
private float m_y = 100.0f;
private float m_z = 100.0f;
private float m_radius = 100.0f;
public float X
{
get { return m_x; }
set { m_x = value; }
}
public float Y
{
get { return m_y; }
set { m_y = value; }
}
public float Z
{
get { return m_z; }
set { m_z = value; }
}
public float Radius

42

Extending the Data Domain

{
get { return m_radius; }
set { m_radius = value; }
}
}

This basic object is a valid custom domain object that can participate in Petrel behavior. It can be
added to the Petrel Input and Model trees.

Adding to Input and Models Trees


The Input tree and the Models tree support the addition of new nodes (domain objects) via the
Project domain object.

Adding to Native Petrel Domain Objects


Custom domain objects may be added as children to some native Petrel domain objects using
the Slb.Ocean.Petrel.Basics.IExtensions interface:
public interface IExtensions : IEnumerable<object>, IEnumerable
{ ...
void Add(

object item );

bool Remove(

object item );

bool Contains( object item );


}

Use the Project.Extensions property to add to the Input tree, and the Project.ModelsExtensions
property to add to the Models tree. You must use a transaction when adding the children. The
transaction is created by the DataManager class. Lock the object that is going to have new
children, then commit the transaction to complete the operation.
using (ITransaction txn = DataManager.NewTransaction())
{
Project proj = PetrelProject.PrimaryProject;
txn.Lock(proj);
proj.Extensions.Add(new XYZObj( ));
proj.ModelsExtensions.Add(new XYZObj( ));
txn.Commit();
}

Figure 13 XYZ Object in Input and Models Trees

This example adds a XYZObj custom domain object to a Borehole, a native Petrel domain object.
Begin with a Borehole object. Lock the Borehole since you are going to change its children. Add
a new XYZObj using IExtensions. Putting it all together, you have the following:
Slb.Ocean.Petrel.DomainObject.Well.Borehole bore = ...;
using (ITransaction txn = DataManager.NewTransaction())
{
txn.Lock(bore);
bore.Extensions.Add(new XYZObj());
txn.Commit();

43

Extending the Data Domain

The following figure shows the result.

Figure 14: XYZ Object added to a Borehole object (A10)

Adding an Object from a Context Menu


All native Petrel objects have context menus that appear when the user right clicks on the object
in the tree.
In the next example, you will add a context menu item to the Borehole context menu, which will
add a XYZObj as a child.
To do so, complete the following procedure:
Define a context menu item using the SimpleContextMenuHandler<TDomainObject> class:
public class SimpleContextMenuHandler<TDomainObject> :
ContextMenuHandler<TDomainObject> where TDomainObject : class
{ ...
public SimpleContextMenuHandler ( string, System.Drawing.Bitmap,
bool, ContextMenuClickedEventHandler<TDomainObject> );
}

Add the new context menu item in the modules IntegratePresentation method. Create a
Borehole context menu item. Add it to the Petrel UI using the PetrelSystem.ToolService service.
SimpleContextMenuHandler<Borehole> cItem =
new SimpleContextMenuHandler<Borehole>(Insert XYZ object,
PetrelImages.Ball, false, AddXYZClick );
PetrelSystem.ToolService.AddContextMenuHandler( cItem );

Provide an event handler to respond to the click of the context menu item. The AddXYZClick
event handler will add the XYZObj object to the Borehole from the context menu.
public void AddXYZClick( object sender, ContextMenuClickedEventArgs<Borehole> e )
{
Borehole bore = e.ContextObject as Borehole;
using (ITransaction txn = DataManager.NewTransaction())
{
txn.Lock(bore);
bore.Extensions.Add(new XYZObj());
txn.Commit();
}

44

Extending the Data Domain

The new Insert XYZ object context menu item is added to the bottom of the Borehole context
menu as shown in the following figure.

Figure 15 Context Menu to Insert XYZ Object

Customizing Tree Presentation


A new custom domain object has a default presentation style when displayed in the tree. The
icon is the Ocean O icon, and the text is object.ToString.

Figure 16 - Default Presentation in Tree

You can control an objects appearance in the Petrel trees by implementing the
Slb.Ocean.Petrel.UI.INameInfoSource and Slb.Ocean.Petrel.UI.IImageInfoSource interfaces
and providing implementations of the abstract NameInfo and ImageInfo classes.
INameInfoSource and IImageInfoSource allow the custom domain object to provide a text string
and a bitmap to be displayed in the user interface. Implementing INameInfoSource and
IImageInfoSource for the XYZObj object is as follows:
using Slb.Ocean.Petrel.UI;
public class XYZObj : INameInfoSource, IImageInfoSource
{ ...
private Bitmap myRedCircle = MyResources.XYZObjImage;
private NameInfo nameInfo;
public NameInfo NameInfo
{
get
{
if (nameInfo == null) nameInfo = new DefaultNameInfo("XYZ Object",
"XYZ Object", "GettingStarted.XYZObj");
return nameInfo;
}
}
private DefaultImageInfo m_imgInfo;
public ImageInfo ImageInfo
{
get
{
if (m_imgInfo == null) m_imgInfo = new DefaultImageInfo(redCircle);
return m_imgInfo;
}
}
}

45

Extending the Data Domain

MyResources contains a resource for the custom bitmap.

Figure 17 - Custom Presentation of XYZ Object

Rendering a Custom Domain Object


A custom domain object may be rendered in standard Petrel windows. The 3D and 2D windows
render data using OpenInventor (Oiv). The Map, Intersection, and Interpretation windows use
.NET GDI+ to render data, and the WellSection window uses INT GeoToolkit.

3D Window Display
You must perform the following steps to render a custom object in the 3D or 2D window.

Implement a renderer for the 3D window for the object type.

Add the renderer service to Ocean.

Implement the IWindow3DRenderer interface to provide a renderer for the 3D window for
displaying your object. Create a class to implement IWindow3DRenderer and implement the
following IWindow3DRenderer methods. CanCreate determines if the domain object can be
rendered in the window. It can use properties of the object or the context to decide. Create is
called the first time an OpenInventor scenegraph is needed to display an object. It creates the
OpenInventor node structure. The position of the XYZObj object is translated into the window
coordinates. A sphere is defined to represent it, and is added to the node hierarchy. The Update
method is called when the scenegraph may be stale. (Refer to OpenInventor documentation for
details.) Dispose should clean up any resources associated with the scenegraph and the node
you are sent.
The complete OpenInventor factory class for rendering the XYZObj object is shown in the
following example:
using OIV.Inventor.Nodes;
using Slb.Ocean.Petrel.DomainObject;
using Slb.Ocean.Petrel.UI;
public class MyXYZ3DRenderer : IWindow3DRenderer
{
public bool CanCreate( object o, Window3DContext ctx )
{
return true;
}
public SoNode Create( object o, Window3DContext ctx )
{
XYZObj xyz = o as XYZObj;
SoSeparator root = new SoSeparator( );
OIV.Inventor.SbVec3f vec3 = window.WorldToWindow(new Point3(xyz.X, xyz.Y,
xyz.Z));
// Create a translation
trans = new SoTranslation();

46

Extending the Data Domain

trans.translation.Value = vec3;
root.AddChild(trans);
// create a sphere
mySphere = new SoSphere();
mySphere.radius.Value = xyz.Radius;
root.AddChild(mySphere);
return root;
}
public void Update(SoNode n, object o, Window3DContext ctx)
{
return; // nothing in this example
}
public void Dispose(SoNode n, object o, Window3DContext ctx )
{
n.Dispose();
}
}

Add the OpenInventor factory as a service in the modules Initialize method to display the
XYZObj object.
public void Initialize ( )
{
Type objType

= typeof( XYZObj );

Type factoryType = typeof(IWindow3DRenderer);


XYZObjOivFactory factory = new MyXYZ3DRenderer( );
CoreSystem.Services.AddService( objType, factoryType, factory);
}

When a 3D window is active, the XYZObject object will have a checkbox next to it indicating that
it may be displayed.

Figure 18 XYZ Object Ready to Display in 3D Window

When the end user clicks the checkbox the object will be displayed.

Figure 19 XYZObj Object in 3D Window

47

Extending the Data Domain

Map Window Display


Complete the following steps to render the custom domain object in the Map window:

Implement the IMapWindow factory interface.

Add the factory to Ocean as a service.

Implement the IMapRenderer interface to display the XYZObj. Define the class that implements
the IMapRenderer interface. In this example, you will render the object as a filled circle.
Implement the Initialize method and set the rendering layer in which the object should be
drawn. The CanDraw method reports whether or not the renderer knows how to draw the
object. In this example, it will always return true. Draw renders a representation of the object
into the window using the appropriate GDI+ drawing surfaces. It obtains the world coordinates
from the context for drawing. It defines the brush style and color and uses the properties of the
XYZObj instance to draw a filled ellipse. GetBounds computes the bounding box that the
instance occupies and returns a Box2. Dispose has nothing to do for this simple XYZObj object.
The complete IMapRenderer implementation for XYZObj is as follows:
using System.Drawing;
using System.Drawing.Drawing2D;
using Slb.Ocean.Geometry;
using Slb.Ocean.Petrel.UI;
public class XYZObjMapDisplay : IMapRenderer
{
public void Initialize ( object o, MapRendererContext ctx )
{
ctx.RenderingLayers = RenderingLayers.Solid;
}
public bool CanDraw ( object o, MapRendererContext ctx )
{
return true;
}
public void Draw ( object o, MapRendererContext ctx )
{
// Get the World coordinates
Graphics gworld = ctx.World;
using (Brush br = new SolidBrush(Color.Blue))
{
XYZObj xyz = (XYZObj)o;
int x = (int)xyz.X;
int y = (int)xyz.Y;
int size = (int)xyz.Radius;
// Draw the circle
gworld.FillEllipse(br, x-size, y-size, size*2, size*2);
}
}
public Box2 GetBounds ( object o, MapRendererContext ctx )

48

Extending the Data Domain

{
XYZObj xyz = (XYZObj)o;
double x = xyz.X;
double y = xyz.Y;
double size = xyz.Radius;
Point2 begin = new Point2( x - size, y - size );
Point2 end = new Point2( x + size, y + size );
// Return a box that describes the area the object occupies
return new Box2( begin, end );
}
public void Dispose ( object o, MapRendererContext ctx )
{
return;
}
}

Register the drawing service with Ocean in the modules Initialize method.
Type

xyzType

Type

factoryType = typeof(IMapRenderer);

= typeof(XYZObj);

XYZObjMapDisplay mapFactory = new XYZObjMapDisplay();


CoreSystem.Services.AddService(xyzType, factoryType, mapFactory);

When the end user checks the checkbox, the XYZObject is rendered in the Map window.

Figure 20 XYZ Object in Map Window

Saving Custom Domain Objects


You may save a custom domain object into the Petrel project using a structured archived data
source provided or a custom data source. If the structured archive data source does not meet
your needs, then you should use the custom data source approach; information for it may be
found in the IDataSource interface documentation for the Ocean API. For the simple example
here we will illustrate saving the custom XYZ object using the structured archive data source.

49

Extending the Data Domain

Structured Archive Data Source


To use the structured archive data source:

Implement DataSourceFactory and create the data source.

Make the class IIdentifiable.

Tag the class and its member to serialize with attributes.

Add the data source factory to register the data source.

Add your custom domain object to a Petrel tree.

You have a new DataSourceFactory class to register the data source. Here you will create the
structured data source with a unique identifier, and you will provide a list of the type of object(s)
to serialize using the structured archive data source.
class XYZObjDataSourceFactory : DataSourceFactory
{
// singleton instance of data source
private static string DataSourceId = UniqueXYZObjDataSourceId";
public static StructuredArchiveDataSource Get(IDataSourceManager dsm)
{
return dsm.GetSource(DataSourceId) as StructuredArchiveDataSource;
}
public override Slb.Ocean.Core.IDataSource GetDataSource()
{ // create data source with unique id and type of object to be saved
return new StructuredArchiveDataSource( DataSourceId, new[] {typeof(XYZObj)});
}
}

Have the XYZObj class implement IIdentifiable. You will use the structured data source to
generate the Droid and add a custom object instance to the data source. Make the following
additions to your XYZObj class.
public class XYZObj : ..., IIdentifiable
{ ...
Droid m_droid;
StructuredArchiveDataSource m_dataSource;
// add Constructor
public XYZObj()
{
IDataSourceManager mgr = DataManager.DataSourceManager;
this.m_dataSource = XyzObjDataSourceFactory.Get(mgr);
this.m_droid = datasource.GenerateDroid();
datasource.AddItem(m_droid, this);
// set initial values:
m_x = 100.0f; m_y = 0.0f; m_z = 0.0f; m_radius = 100.0f;
}
public void Droid Droid
{
get { return m_droid; }
}
}

You must also tag your class and any members you want to serialize into the structured archive
50

Extending the Data Domain

data source with one of the following attributes:

ArchivableAttribute on the class

ArchivedAttribute on the member

Add the attributes to your XYZObject.


[Archivable]
public class XYZObj : IIdentifiable, ...
{ ...
[Archived]
float m_x;
[Archived]
float m_y;
[Archived]
float m_z;
[Archived]
float m_radius;
// can provide name:
[Archived(Name = Droid)]
Droid m_droid;
StructuredArchiveDataSource m_dataSource;
}

You must register your data source factory with the system in your Module.Integrate using
the PetrelSystem.AddDataSourceFactory method:
public class Module : IModule, ...
{ ...
public void Integrate()
{ ...
PetrelSystem.AddDataSourceFactory(new XYZObjDataSourceFactory);
}
}

Next you will create your object and add it to the tree, providing the data source instance in the
objects constructor. You will retrieve your data source factory from the Get method you added
to it above.
public void CreateXYZObj()
{
// create XyzObj instance and provide data source
XyzObj xyz = new XyzObj();
Project project = PetrelProject.PrimaryProject;
using (ITransaction t = DataManager.NewTransaction())
{
t.Lock(project);
// Add XyzObj to project extensions.
project.Extensions.Add(xyz);
t.Commit();
}
}

When you save the project, the XYZObject is saved with it. Reopening the project will load this
data back into Petrel.

51

Appendix
The Ocean Wizard

APPENDIX
THE OCEAN WIZARD
Ocean provides a Wizard to simplify the creation and installation of modules. This chapter
provides an overview of the Ocean Module Wizard and its features.

Installing the Ocean Wizard


The Ocean Wizard is installed as part of the Ocean SDK installation process. Installation of the
Wizard is an option and requires some disk space. Although it is part of the typical installation, it
might not have been part of your installation. If the Wizard has not been installed, you will need
to install it before you can go any further.
To install the Wizard:
1. Run your Ocean SDK installation executable again.
2. Select Modify.
3. Add the Wizard using the settings in the associated boxes.

Figure 1: Installing the Ocean Wizard

To check whether the Ocean Wizard has been installed, run Visual Studio and select New Project
from the File menu. The project dialog should show Ocean as an option in the list of new project
types as shown in the following figure.

52

Appendix
The Ocean Wizard

Figure 2: New Project Dialog Showing the Ocean Wizard Options

If these icons are not shown, run the Ocean SDK installer again and select the Wizard installation
option.
If you try to add a new project item to an existing project (as shown in Figure 3), then you can
see the Ocean project item types (as shown in Figure 4).

Figure 3: Add / New Item Context Menu on the Solution Explorer

53

Appendix
The Ocean Wizard

Figure 4: New Project Item Dialog Showing the Ocean Wizard Installed Options

Creating an Ocean Plug-in Project


If you want to create a new plug-in project, choose File > New Project in Visual Studio. The
following screen opens.

Ocean Plugin
Ocean
project
types

Project name

Figure 5: Creation of an Ocean Plug-in Dialog

The following figure shows the Step 1 window of the plug-in project or plug-in file wizard:

54

Appendix
The Ocean Wizard

Figure 6: Step 1 of Plug-in Wizard Dialog

In this page, you can specify the plug-in metadata information such as the author, contact
information, and a small description. This information is redundant if you use the old
IModuleAppearance on your modules, but the information given in the plug-in will be the main
source.
If you check the Register existing modules in the solution checkbox, then you can select which
modules want to register from the detected module list:

Figure 7: Step 2 of Plug-in Wizard Dialog

In order to use the plug-in, there must be at least one module registered in it.
You also have the option to generate a new module together with the new plug-in. If you choose

55

Appendix
The Ocean Wizard

to generate a new module, you will get the same module-generator wizard pages you are
already familiar with.
During the building of your plug-in, as a post build event, the plug-in gets registered in Petrel, so
you need to build your plug-in at least once, and after that, the plug-in is usable from Petrel.

Module class name


Module namespace

Petrel executable file

Plugin registration

Figure 8: Step 1 of Module Wizard Dialog

To begin creating your new module:


1. Specify the following options:

Name: Enter the name of the module class. For this example, change the module name
from OceanModule1 to Module.

Namespace: Define the namespace for your module projects class. It is a common
practice when defining namespaces to incorporate the company name and product
name into the namespace to avoid conflict. In this example, you must change the
namespace from OceanModule1 to Slb.Ocean.HelloWorldSample.

Generate IModuleAppearance implementation: Check this option to generate a class


that would implement IModuleApperance interface. The Wizard will annotate your
Module class with the ModuleAppearance attribute. For more information and details
of IModuleAppearance, refer to the Ocean API documentation or the Ocean Developers
Guide.

Generate Workspace Events: Check this option to register for DataManager.Workspace


events in the Initialize method of your Module class.

Location of Petrel Application: Using the browser () button, provide the location of
petrel.exe file. This will enable the Wizard to set the project configuration to run the
Petrel application for instant debugging. Also, the necessary references will be selected
relative to this path.

The following options allow you to add additional ocean items to the project.

56

Appendix
The Ocean Wizard

New Window: Check this option to implement and add a custom window to your
module project. For more information, refer to Adding a New Window.

New Workstep: Check this option to add a new workstep to your module project. For
more information, refer to Adding a New Workstep.

New Menu Item: Check this option to add a new menu item to the existing Petrel
menus. For more information, refer to Adding a New Petrel Menu Extension.

Input Tree Extension: Check this option to add a new extension to the Petrel tree data
items. For more information and details, refer to Adding a New Petrel Tree Extension.

You can also add all of these items to the project later; these checkboxes are only shortcuts.
They allow you to create a module with the most usual module elements at once. Their Wizard
pages are exactly the same as the standalone Workstep, Menu Item, and Tree Extension Project
Item Wizard pages.
2. Click Next.
The Step 2 screen of the Wizard dialog opens as shown in the following figure.

Figure 9: Step 2 of the Wizard Dialog

This step shows a list of the items that will be created. Some of the most important settings are
also listed.
3. Click Finish.
The Ocean Wizard generates an Ocean Plug-in project with the name provided in the Name
textbox (See Figure 5). Ocean Wizard also generates a file with Module class, which implements
the IModule interface and adds this Ocean module to your new Ocean Plug-in project.
The following figure shows a preview of the Solution Explorer for the newly generated Ocean
Plug-in project.

57

Appendix
The Ocean Wizard

Figure 10: Solution Explorer of the Newly Created Plug-in Project

Adding a New Process


If you chose Ocean Process in the Add / New Item dialog (Figure 3), then the following screen
opens:

Check the register option to enable module selection


dropdown.

Namespace of the
selected module

Module
selection
dropdown

Figure 11: Register in Module Page

1. Specify the appropriate options.


An Ocean Plug-in assembly may contain more than one module. This page lets you decide where

58

Appendix
The Ocean Wizard

to register your new process or whether to register it at all. The detected modules are listed in
the dropdown list.
Important: The same page appears for all Ocean project item types (except the Module itself),
and its purpose is the same: to register the generated item in the selected module.
2. Click Next.
The following screen opens:

Set Project name


Set short description

Set the detailed description

Add workstep
Workstep list

Edit the selected workstep


Remove workstep

Figure 12: Ocean Process Details

3. Enter the appropriate information in the following fields:

Process name: Enter the name of the process class.

Short description: Enter a brief explanation of the purpose of the process.

Long description: Provide a more detailed explanation of what a process does. Your
description might include the type of data provided for each of the arguments.
4. Click Add to add a workstep. It will open the Workstep Generator
dialog as shown in the following figure:

59

Appendix
The Ocean Wizard

Workstep class name


Workstep file name

Check this to manually set the file name

Figure 13: Ocean Workstep Generator

The Workstep Generator dialog contains the following three tabs:

File settings: The worksteps are created into different files, and each workstep has its
own source file. On this tab, you can set the file name and class name of the workstep.
For detailed instructions, see Adding a New Workstep for details.

Workstep data: This tab is similar to the main page of the process. You can set the name,
description, and other settings. This tab is exactly the same as on the second page of the
Ocean Workstep project item wizard; see Adding a New Workstep for details.

Argument data: This tab is used for setting the arguments of the workstep. See Adding a
New Workstep for details, because it is exactly the same as the third page of the Ocean
Workstep project item wizard.
5. After you set the workstep, click OK to return to Ocean Process
Details.

In this example, the newly created HelloWorldWorkstep is added to the workstep list as shown
in the following figure.

60

Appendix
The Ocean Wizard

Newly created workstep

Figure 14: Creation of a New Workstep

6. Click Next.
The Wizard generates a file with the Process class and a file with the Workstep class and adds
them to the process diagram and workflow editor respectively. The Wizard also adds the
following code in the Integrate method of your Ocean module class:
public void Integrate()
{
// Registrations:
// TODO:

Add Module.Integrate implementation

// Register HelloWorldProcess
HelloWorldProcess helloworldprocessInstance = new
HelloWorldProcess();
PetrelSystem.ProcessDiagram.Add(helloworldprocessInstance, "Plugins");
// Register HelloWorldWorkstep
HelloWorldWorkstep helloworldworkstepInstance = new
HelloWorldWorkstep();
PetrelSystem.WorkflowEditor.Add(helloworldworkstepInstance);
PetrelSystem.ProcessDiagram.Add(new
Slb.Ocean.Petrel.Workflow.WorkstepProcessWrapper(helloworldworkstepInsta
nce), "Plug-ins");
}

The following figure shows a preview of the process as well as the workstep files in the Ocean
Plug-in project.

61

Appendix
The Ocean Wizard

Figure 15: Preview of Solution Explorer with Process and Workstep Files

Adding a New Petrel Menu Extension


If you chose Ocean Menu Extension from the Add/New Item option from the Visual Studio
context menu (Figure 3), or if you checked the option to add a new menu in Step 1 of the Wizard
dialog (Figure 8: Step 1 of Module Wizard Dialog), then you will see the following Wizard screen:

62

Appendix
The Ocean Wizard

Add new menu item

Delete menu item

Type of
menu item
Menu text

Turn on event

Position settings

Figure 16: Petrel Menu Extension Details

From this screen, you can add menu items, create new main menu items, or extend existing
Petrel menus with new items. You must always select the parent item to which the new item will
be added.
The types of the menu items that can be added include the following:

Button: normal menu item. It can be clicked to fire an event.

State Button: This option can be used in order to add a parameter setting in the menu.
Selecting the item toggles it on; selecting it again reverses the process and toggles it off.

Combo Box: This option adds a combo box to the menu as a menu item. The Wizard
allows you to select the labels for the items in the combo box as well as the type of data
those items represent. They type options are string, integer, double, and object.

Popup menu: A popup menu is a new menu added to the main menu bar, or a menu
that cascaded from an item within a menu. In such a case it will have a right-pointing
arrow indicating the cascade.

Separator menu: This is a separator that is displayed as a line. It cannot be clicked.

The following figure shows an event handler class file in Solution Explorer.
The Position Group setting is a new option in the Ocean for Petrel 2012 release. With this option,
you can specify the position of the new menu item you want to create. It does not give full
control over the position of the new item, but you can specify the group where the menu item
belongs. Each main menu has its own groups to choose from.

63

Appendix
The Ocean Wizard

Figure 17: File Containing Menu Event Handlers in Solution Explorer

In addition to the event handler class file, the Wizard will also add the following code in the
IntegratePresentation method of your module class.
public void IntegratePresentation()
{
// Registrations:
// TODO: Add Module.IntegratePresentation implementation
HelloWorldMenu.AddNewMenuItemsUnderHelloWorld1();
}

Adding a New Petrel Tree Extension


If you chose Ocean Tree extension from the Add/New Item option from the Visual Studio
context menu (Figure 3), or if you checked the Input tree extension option in Step 1 of the
Wizard dialog (Figure 8: Step 1 of Module Wizard Dialog), then you will see the following Wizard:

64

Appendix
The Ocean Wizard

Add new item


Add new folder
Delete button

Newly created extension folder

Newly created extension item

Figure 18: Ocean Tree Extension Details

1. Click the Add Extension button or Add Extension Folder button.


2. Enter the appropriate information.
For every tree extension, the Wizard generates a file with the tree item class and a file with tree
item factory class, files with name and info classes. In this example, the Wizard will generate the
following files:

HelloWorldTreeitem.cs

HelloWorldTreeitemFactory.cs

HelloWorldTreeitemImageInfo.cs

HelloWorldTreeitemNameInfo.cs

For every tree extension folder, the Wizard generates a file with tree folder class, a file with
factory class, and two files with image and name info classes. In this example, the Wizard will
generate the following files:

HelloWorldTreeFolder.cs

HelloWorldTreeFolderFactory.cs

HelloWorldTreeFolderImageInfo.cs

HelloWorldTreeFolderNameInfo.cs
3. Click Next.

The following figure shows a preview of files created by the Wizard in Solution Explorer.

65

Appendix
The Ocean Wizard

Figure 19: Tree Extension Files in Solution Explorer

In the module file, the Integrate method will be extended with the following lines:
public void Integrate()
{
// Registrations:
// TODO: Add Module.Integrate implementation
CoreSystem.Services.AddService(typeof(HelloWorldTreefolder),
typeof(Slb.Ocean.Petrel.UI.INameInfoFactory),
HelloWorldTreefolderFactory.Instance);
CoreSystem.Services.AddService(typeof(HelloWorldTreefolder),
typeof(Slb.Ocean.Petrel.UI.IImageInfoFactory),
HelloWorldTreefolderFactory.Instance);
CoreSystem.Services.AddService(typeof(HelloWorldTreeitem),
typeof(Slb.Ocean.Petrel.UI.INameInfoFactory),
HelloWorldTreeitemFactory.Instance);
CoreSystem.Services.AddService(typeof(HelloWorldTreeitem),
typeof(Slb.Ocean.Petrel.UI.IImageInfoFactory),
HelloWorldTreeitemFactory.Instance);
}

Adding a New Window


If you chose Ocean Window from the Add/New Item option from the Visual Studio context
menu (Figure 3), or if you checked the option to add a window in Step 1 the Wizard dialog
(Figure 8), then the Wizard generates a file with Window class. In addition to the class file, Ocean
Wizard also generates a default UserControl with the same name as the Window field (Figure 8)
and appended by UI as the class name.
In this example, you entered HelloWorldWindow in the New Window field (Figure 8), and
the wizard generated the following files:

66

HelloWorldWindow.cs: contains the Window class which implements IImageInfoSource,


INameInfoSource interfaces and inherits from ToggleWindow base class.

HelloWorldWindowImageInfo.cs: contains ImageInfo class.

Appendix
The Ocean Wizard

HelloWorldWindowNameInfo.cs: contains NameInfo class.

HelloWorldWindowUI.cs: contains UserControl class.

The following figure shows a preview of files created by the Wizard in Solution Explorer.

Figure 20: Preview of Solution Explorer Containing Window Class Files

Adding a New Workstep


If you chose Ocean Workstep from the Add/New Item option from the Visual Studio context
menu (Figure 3), or if you checked the option to add a window in Step 1 of the Wizard dialog
(Figure 8), then you will see the following Wizard page.

67

Appendix
The Ocean Wizard

Figure 21: Second Page of the Ocean Workstep Wizard

This page is similar to the general settings page of the Ocean process (Figure 12).
1. Enter the appropriate information.
The name will be displayed in the process tree of Petrel, and the
descriptions will be displayed on the default process UI.
2. Click Next.
3. On the next page (shown below), set the arguments of the
workstep. These arguments are input and output variables that will
be used by the workstep during its work.

Add new argument


Delete selected argument

New Borehole
argument
Controls for editing
the argument

Figure 22: Workstep Argument Setting Page of the Wizard

68

Appendix
The Ocean Wizard

The Wizard adds the following code in the Integrate method of the selected module class:
public void Integrate()
{
// Registrations:
// TODO:

Add Module.Integrate implementation

// Register HelloWorldWorkstep
HelloWorldWorkstep helloworldworkstepInstance = new
HelloWorldWorkstep();
PetrelSystem.WorkflowEditor.Add(helloworldworkstepInstance);
PetrelSystem.ProcessDiagram.Add(new
Slb.Ocean.Petrel.Workflow.WorkstepProcessWrapper(
helloworldworkstepInstance), "Plug-ins");
}

Adding an Ocean Settings Page


You can use the Wizard to generate custom Settings Pages by choosing Ocean Settings Page on
the Add New Item dialog of Visual Studio (Figure 4). After completing the Wizard steps, you will
see the following files:

Figure 23: Ocean Settings Page in the Solution Explorer

The Wizard generates a UserControl, which will be the SettingPage class, and a
SettingPageFactory class.

69

Appendix
The Ocean Wizard

In this example, you provided the default DialogPage1 as the name in the Visual Studio Item
dialog, and the Wizard generated the following files:

HelloWorldDialogPage.cs

HelloWorldDialogPageFactory.cs

If you checked the Register new classes in module option in the Visual Studio Item dialog (Figure
11), then the Wizard adds the following code in the IntegratePresentation method of the
selected module class.
public void IntegratePresentation()
{
// Registrations:
// TODO: Add Module.IntegratePresentation implementation
PetrelSystem.DialogBuilder.AddFactory(new
HelloWorldDialogPageFactory());
}

Adding Ocean Data Sources


The Ocean Wizard allows you to add data sources only to existing Ocean module projects. (See
Figure 3 and Figure 4.) The Wizard only adds the framework to handle a data source. For
additional details on adding data sources, refer to the Ocean Developers Guide.
The following figure shows a preview of the Solution Explorer with the generated data source
class file.

Figure 24: The Solution Explorer Showing the New Data Source Class File

If you checked the Register new classes in module option in the Visual Studio Item dialog (Figure
11), then the Wizard adds the following code in the Integrate method of the selected module.

70

Appendix
The Ocean Wizard
public void Integrate()
{
// Registrations:
// TODO: Add Module.Integrate implementation
PetrelSystem.AddDataSourceFactory(
HelloWorldDataSourceFactory.Instance);
}

Adding an Ocean Seismic Attribute


If you chose Ocean Process in the Add/New Item dialog (Figure 3), then the following screen
opens:

Figure 25: Ocean Seismic Attribute Wizard Page

1. Enter the appropriate information.


Open the Geophysics / Volume attributes in Petrel to find the Petrel equivalents of the Ocean
Seismic attributes. You can add your own attribute to that processs attributes. The name,
description, and category of the attribute are self explanatory.
The Ocean Seismic attribute represents an operator that completes calculations on a seismic
cube. The operator size represents how many data samples the operator needs around the
actual cell from the 3D data space. The attribute may have multiple input seismic cubes too.
2. Click Next.
The following figure shows a preview of the Solution Explorer with the generated seismic
attribute class file:

71

Appendix
The Ocean Wizard

Figure 26: Custom Seismic Attribute in the Solution Explorer

The following source lines are added to the Integrate method of the module if the register
option is enabled on the first page of the Wizard:
public void Integrate()
{
// Registrations:
// TODO: Add Module.Integrate implementation
if (PetrelSystem.SeismicAttributeService == null)
throw new LifecycleException("Required AttributeService is not
available.");
PetrelSystem.SeismicAttributeService.AddSeismicAttribute(new
HelloWorldAttribute());
}

Adding an ECLIPSE Format Simulator Plug-in


This Ocean Wizard allows you to generate an ECLIPSE Format Simulator plug-in into your Ocean
module. All files generated via this Wizard will be located under the SimulatorPlugin folder in
your project.

72

Appendix
The Ocean Wizard

1. Enter your plug-in simulator file name in the Add New Item
dialog box (Figure 27). Note that if you use an existing file name,
the old file will be overwritten by the new one. Click Add to
proceed.

Figure 27: Ocean ECLIPSE Format Simulator template in Add New Item dialog box

2. In this wizard page (Figure 28), you can choose the ECLIPSE deck
type and whether you want to export keywords or not. Click
Next to proceed or click Cancel to quit the wizard.

Figure 28: Deck Type and Export Keywords Option dialog box

73

Appendix
The Ocean Wizard

3. All Grid Formats are supported by default. You can change the
supported grid formats here (Figure 29).

Figure 29: Supported Grid Formats dialog box

4. From the Custom Tab Option dialog box (Figure 30), you can set an
option whether to create a custom tab or not. This custom tab will
appear in the Petrel Define Simulation Case dialog when your
simulator is selected. You can input the class and tab names but the
added custom tab will use a default icon image. This icon can be
changed by overriding the IAppearance::Image property once the
wizard has finished.
If the check box is ticked then the following files will be generated (where Xxx is your class name)
and added along with the EclipseFormatSimulator1.cs file:

74

XxxTabArguments.cs,

XxxTabControl.cs,

XxxTabLogic.cs

XxxTabUIFactory.cs

Appendix
The Ocean Wizard

Figure 30: Custom Tab Option dialog box

5. In this step, you can decide whether to register your plug-in to the
Ocean module or not.

Figure 31: Ocean File Add dialog box

75

Appendix
The Ocean Wizard

6. The last step of the Wizard (Figure 32) shows a summary of the files
which will be added to the project. In this example, only one file
named EclipseFormatSimulator1.cs has been added (since the
custom tab option was not ticked). If you tick the custom tab option,
the appropriate files mentioned in step 4 will be also added to the
SimulatorPlugin folder. You can also add additional references
(assemblies) by ticking the Additional Reference settings check box.

Figure 32: Completing settings dialog box

Adding a Plug-in project


More than one plug-in project can be added to the same solution. The plug-in project allows you
to generate a basic plug-in implementation with additional project settings to help developing
the plug-in. Basically, a plug-in groups multiple modules together, and lets you set up
dependency between plug-ins.
There are some rules and recommendations using the plug-ins. These are checked by Wizard:

In a solution there should be only one plug-in. If there are 2 or more, then they should
contain only different modules. One module must belong to only one plug-in. The wizard
warns you when you try to create a new plug-in when there is another one already:

Figure 33: Warning message. Another plug-in is detected in the solution.

76

Appendix
The Ocean Wizard

In one project there has to be one (and only one) plug-in. This is a very strict rule; do not
create more than one plug-in class into a project. The wizard lets you do it, but we warn
you, that the registration of such a plug-in will fail; you will not be able to use any of
those plug-ins.

Generating a plug-in project or file:

Figure 34: Plug-in wizard, 1st page.

In this page, you can specify the plug-in metadata information such as the author, contact
information and a description. This information is redundant if you use the old
IModuleAppearance on your modules, but the information given in the plug-in will be the main
source.
If you check the Register existing modules in the solution checkbox, then you can select which
modules want to register from the detected module list:

77

Appendix
The Ocean Wizard

Figure 35: Plug-in wizard, 2nd page.

In order to use the plug-in, there must be at least one module registered in it.
You also have the option to generate a new module together with the new plug-in. If you choose
to generate a new module, you will get the same module-generator wizard pages you are
already familiar with.
During the building of your plug-in, as a post build event, the plug-in gets registered in Petrel, so
you need to build your plug-in at least once, and after that, the plug-in is usable from Petrel.

Adding a New Property Modeling Algorithm


If you chose Ocean Property Modeling algorithm in the Add / New Item dialog then you will see
the following Wizard page.

78

Appendix
The Ocean Wizard

Figure 36: Second page of Property Modeling wizard

Geometrical modeling algorithm


For adding a new geometrical modeling algorithm select Geometrical modeling algorithm type
(Figure 36). Specify the following options:

Title: Enter the title of the algorithm. This text will be displayed on the Geometrical
modeling process dialog.

Generate custom UI: If selected wizard will generate an empty UserControl and the
necessary UI registration code

Algorithm can model dictionary properties: If selected generated algorithm will be


present in Geometrical modeling if a dictionary property is selected.

Algorithm supports all dictionary templates: Generated code will return all dictionary
templates, otherwise SupportedDictionaryTemplates method needs to be filled with
supported templates.

Algorithm can model continuous properties: If selected generated algorithm will be


present in Geometrical modeling if a continuous property is selected.

Algorithm supports all continuous templates: Generated code will return all continuous
templates, else SupportedTemplates method needs to return supported templates.

After building the project and starting Petrel start geometrical modeling process. You will see the
algorithm in the geometrical modeling UI (Figure 37). It can be executed but will do nothing.
//TODO sections in the code must be filled to get a meaningful algorithm.

79

Appendix
The Ocean Wizard

Figure 37: Geometrical modeling algorithm in Petrel

Facies modeling algorithm


For adding a new facies modeling algorithm select Facies modeling algorithm type. (Figure 38)

Figure 38: Facies modeling algorithm

Specify the following options:

80

Title: Enter the title of the algorithm. This text will be displayed on the Facies modeling
process dialog.

Appendix
The Ocean Wizard

Generate custom UI: If selected wizard will generate an empty UserControl and the
necessary UI registration code

After building the project and starting Petrel start facies modeling process. You will see the
algorithm in the facies modeling UI (Figure 39). It can be executed but will do nothing. //TODO
sections in the code must be filled to get a meaningful algorithm.

Figure 39: Facies modeling algorithm in Petrel

Petrophysical modeling algorithm


Identical to facies modeling.

Adding a PIP Project


This project type generates an installation package, what the Petrel application can consume.
Instead of using the operating system to install and manage extensions, let Petrel do the work,
and manage its extensions by itself. This is the way to deploy modules and plug-ins. However,
the PIP package cannot cover special use cases such as pre/post installation steps, custom
actions, installation of 3rd party prerequisites, etc. In case your plug-in package needs such
installation steps, please see the Ocean Plug-in Installer project.
Prerequisite: the solution has to contain at least one plug-in project (project with a plug-in class).

81

Appendix
The Ocean Wizard

Figure 40: PipBuilder project

Figure 41: PipBuilder project wizard

In the wizard page, you can specify the main plug-in for this PIP file. The PIP file must have one
and only one plug-in in it, this plug-in will be detected by the PluginPackager, and it will be
registered into the PluginManager during the installation of the PIP.
In the checklistbox, you can add additional projects from the actual solution. The output of the
selected projects will be added to the PIP file together with the plug-in container assembly.
Note: currently the wizard does not support dependency detection for the plug-in assembly. It
means, that in case the plug-in assembly (or any other assembly selected in the checklistbox) has
a dependency to another project, then it will not be added to the PIP file automatically. You
have to add all of the required dependencies.

82

Appendix
The Ocean Wizard

Editing the DeployList.xml


The DeployList.xml describes the internal structure of the PIP file. This XML is loaded during the
build of the project, and the DeployCopier command line tool (placed to the project directory by
the Wizard) will copy all the files and project outputs registered in this xml to a temporary
folder. It also keeps their folder hierarchy settings. From this temporary folder, the
PluginPackager tool (deployed by the Petrel installer to the petrel root folder) will pack them to
the target folder of the PIP project. (By default: bin\debug and bin\release)
The temporary folder can be changed by editing the Pre and PostBuild events of this project, and
changing the paths containing the copytemp folder.
Deploylist.xml can contain files and project outputs
The files are normal files, they can be resources (pictures, sounds, videos, databases, etc). They
will not be processed, only copied and packed.
The project outputs are project files, preferably from the same solution as the PIP builder project
itself. The project files will be processed by the DeployCopier tool, the output path and compiled
binary file name will be retrieved using the actual platform and configuration settings. At the
end the project output will be copied to the temporary folder.
The OceanSDK installs a new context menu item into Visual Studio. It can be reached by right
clicking on the DeployList.xml file in the Solution Explorer:

Figure 42: Edit DeployList context menu item

83

Appendix
The Ocean Wizard

Clicking on this menu item, a small editor appears:

Figure 43: DeployList editor dialog

In the tree view on the left side contains the folders and files of the Pip file in the same hierarchy
it will be installed on the target machine. Use drag and drop from either the Solution Explorer, or
Windows Explorer to add new files to it.
If you want to add a project output from the existing solution, just drag that project from the
Solution Explorer. The editor detects if the dragged item is a project, and it automatically adds
Project dependencies to that project, so building the Pip file will build that project also.
You can rename the files and folders with F2 key or with clicking on the item again. These
settings will be applied to the target name; it will not change the actual name of the file.

Adding Ocean Plug-in Installer Project


Important: This project is only supported by Visual Studio 2010. We recommend using the Ocean
Wix Plug-in Installer project in case you have Visual Studio 2012.
This project can be used when a simple PIP file installation with PluginManager does not meet
the needs. The result of this project template is an MSI installer project that can be further
customized by adding extra installer actions. It is also possible to combine more than one plugins (PIP files) into one MSI installer as Plug-in bundle. Please note however plug-ins installed
together as bundle cannot be uninstalled individually.
We recommend using the Ocean Plug-in Installer in case you have a special need which the PIP
project cannot handle, e.g.: custom actions, pre/post installation steps, installation of 3rd party
prerequisites, etc.
The recommended way of using this Ocean Plug-in Installer template is to first add one or more
Ocean Plug-in project(s) to the solution then add a PIP Builder project for each plug-in, compile
the PIP builder project(s) then add this Ocean Plug-in Installer project for the PIP file(s).
To add a new Ocean Plug-in Installer to the project:
1. Once you have Ocean Plug-in and PIP Builder project in the solution, compile the PIP
builder project and make the selections shown in the following figure.

84

Appendix
The Ocean Wizard

Figure 44: Visual Studio Context Menu to Add a New Project

2. Choose the Ocean Plug-in Installer on the displayed project dialog. Remember to set the
Project Name. (See Figure 2: New Project Dialog Showing the Ocean Wizard Options)
3. On the first page of the Installer wizard, choose the targeted platform and Ocean for Petrel
version. This selection is necessary because the different Ocean for Petrel versions has
different registration codes, and the correct one should be used for each installation. Also,
if you reference native libraries in your module, you may need to use different DLLs for
each platform:

Figure 45: Installer Wizard First PageSetting the Targeted Platform

4. Click Next.
The Step 2 window opens:

85

Appendix
The Ocean Wizard

Figure 46: Step 2, Setting Title, Company and Description

5. Enter the appropriate information as follows:

Title: The text entered here is displayed on the title bar of the installation kit. In this
example, enter HelloOceanPluginInstaller. This will be displayed in the installed
programs list at Control Panel -> Add Remove Programs.

Company: The text typed here is added to the properties of the MSI kit. This information
can viewed in the summary tab under the properties of install kit.

Description: The text typed here is added to the properties of the MSI kit. This
information can be viewed in the comments section under the properties of the install
kit.
6. Click Next.

The Wizard opens the Step 3 window as shown in the following figure.

86

Appendix
The Ocean Wizard

Check every PIP builder projects that you


want to include in the Installer

Figure 47: Step 3, Setting the Included PIP Builder projects

This dialog lists all of the projects available under the current solution. This example includes the
HelloOceanPlugin Ocean Plug-in project and the HelloOceanPIPPackage PIP Builder project.
This Installer project needs the PIP files (the outputs) of PIP Builder projects. Select those you
want to be included in the installer MSI file. You may add other PIP files manually (not located in
this solution) later.
7. Click Next.
The Wizard opens the Step 4 window as shown in the following figure.

Select the PIP files to include in installer

Figure 48: Step 4, Selecting PIP files

The PIP files from the PIP builder projects selected in the previous step are listed here. If you
selected the PIP Builder project at previous step but the PIP file is still not listed here, please
compile the PIP builder project (the HelloOceanPIPPackage project in this example) and start

87

Appendix
The Ocean Wizard

the wizard again. Only existing PIP files can be added to the installer project.
The plug-in will be installed for all users on the target computer as default.
8. Click Next.
The Wizard displays the summary page with the information what will be installed.
In this example it is:
Plug-ins to install:
HelloOceanPIPPackage.pip that contains the HelloOceanPlugin
9. Click Finish.

Figure 49: Preview of Installer Files in Solution Explorer

The HelloOceanPluginInstaller project has been created and ready to compile. Its output is a
HelloOceanPluginInstaller.msi that can be shipped to the users (or upload to Ocean Store).
Please check the ReadMe.txt file added the project for more options. There is no Primary
project output in the installer project instead, the PIP files are added to the project that you
selected in the wizard. MSI installer will call PluginManager to install these PIP files. There is one
more file worth mentioning, the PluginInstallInfo.xml.

Adding Ocean Wix Plug-in Installer Project


This project can be used when a simple PIP file installation with PluginManager does not meet
the needs. The result of this project template is an MSI installer project that can be further
customized by adding extra installer actions. It is also possible to combine more than one plugins (PIP files) into one MSI installer as Plug-in bundle. Please note however plug-ins installed
together as bundle cannot be uninstalled individually.
We recommend using the Ocean Wix Plug-in Installer in case you have a special need which the
PIP project cannot handle, e.g.: custom actions, pre/post installation steps, installation of 3rd
party prerequisites, etc.

88

Appendix
The Ocean Wizard

The recommended way of using this Ocean Wix Plug-in Installer template is to first add one or
more Ocean Plug-in project(s) to the solution then add a PIP Builder project for each plug-in,
compile the PIP builder project(s) then add this Ocean Plug-in Installer project for the PIP file(s).
To add a new Ocean Wix Plug-in Installer to the project:
1. Once you have Ocean Plug-in and PIP Builder project in the solution, compile the PIP
builder project and make the selections shown in the following figure.

Figure 50: Visual Studio Context Menu to Add a New Project

2. Choose the Ocean Wix Plug-in Installer on the displayed project dialog. Remember to set
the Project Name. (See Figure 2: New Project Dialog Showing the Ocean Wizard Options)
3. On the first page of the Installer wizard, choose the targeted platform and Ocean for Petrel
version. This selection is necessary because the different Ocean for Petrel versions has
different registration codes, and the correct one should be used for each installation. Also,
if you reference native libraries in your module, you may need to use different DLLs for
each platform:

Figure 51: Installer Wizard First PageSetting the Targeted Platform

9. Click Next.
The Step 2 window opens:

89

Appendix
The Ocean Wizard

Figure 52: Step 2, Setting Title, Company and Description

10. Enter the appropriate information as follows:

Title: The text entered here is displayed on the title bar of the installation kit. In this
example, enter HelloOceanWixPluginInstaller. This will be displayed in the installed
programs list at Control Panel -> Add Remove Programs.

Company: The text typed here is added to the properties of the MSI kit. This information
can viewed in the summary tab under the properties of install kit.

Description: The text typed here is added to the properties of the MSI kit. This
information can be viewed in the comments section under the properties of the install
kit.
11. Click Next.

The Wizard opens the Step 3 window as shown in the following figure.

90

Appendix
The Ocean Wizard

Check every PIP builder project that you


want to include in the Installer

Figure 53: Step 3, Setting the Included PIP Builder projects

This dialog lists all of the projects available under the current solution. This example includes the
HelloOceanPlugin Ocean Plug-in project and the HelloOceanPIPPackage PIP Builder project.
This Installer project needs the PIP files (the outputs) of PIP Builder projects. Select those you
want to be included in the installer MSI file. You may add other PIP files manually (not located in
this solution) later.
12. Click Next.
The Wizard opens the Step 4 window as shown in the following figure.

Select the PIP files to include in installer

Figure 54: Step 4, Selecting PIP files

91

Appendix
The Ocean Wizard

The PIP files from the PIP builder projects selected in the previous step are listed here. If you
selected the PIP Builder project at previous step but the PIP file is still not listed here, please
compile the PIP builder project (the HelloOceanPIPPackage project in this example) and start
the wizard again. Only existing PIP files can be added to the installer project.
The plug-in will be installed for all users on the target computer as default.
13. Click Next.
The Wizard displays the summary page with the information what will be installed.
In this example it is:
Plug-ins to install:
HelloOceanPIPPackage.pip that contains the HelloOceanPlugin
10. Click Finish.

Figure 55: Preview of Installer Files in Solution Explorer

The HelloOceanWixPluginInstaller project has been created and ready to compile. Its output is
a HelloOceanWixPluginInstaller.msi that can be shipped to the users (or upload to Ocean Store).
Please check the ReadMe.txt file added the project for more options. There is no Primary
project output in the installer project instead, the PIP files are added to the project that you
selected in the wizard. MSI installer will call PluginManager to install these PIP files. There is one
more file worth mentioning, the PluginInstallInfo.xml.

92

Appendix
The Ocean Wizard

Customizing the PluginInstallInfo.xml


This file contains the information about the plug-ins necessary for PluginManager when
installing or uninstalling the plug-ins.
To edit this file, please right click on it and choose the Open menu item. Double-clicking on it
will not do the same, it will show its file system settings instead.
The structure of this XML is:
<?xml version="1.0"?>
<PluginInstallInfo
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Plugins>
<Plugin Id="://HelloOcean.Plugin/1.0.0.0">
<Name>Plugin</Name>
<PipFilePath>
{Project_Folder}\bin\Debug\HelloOceanPIPPackage.pip
</PipFilePath>
</Plugin>
</Plugins>
</PluginInstallInfo>

Please note the followings:

The < PluginInstallInfo> node is an XML root; there must be only one in the XML
document. The XML must be a valid, well-formed XML.

There can be more than one <Plugin> nodes in the XML, all of them will be used during
the installation/uninstallation.

The PIP files for <Plugin> nodes added manually to the XML should be part of the
installer project and listed in Application Folder in order to be in the MSI file.

Files can be renamed but PIP file content cannot be changed.

If you have more than one Plug-ins in PluginInstallInfo.xml file (and corresponding PIP
files in the project) they are regarded as one bundle and handled as such. That plug-ins
are installed/uninstalled together only.

The Plug-in Manager (that eventually installs the plug-ins) will install what is in the pip files and
ignores all other files deployed by MSI. If you need something extra to what PluginManager does
then you might need to add a Custom Installer step.

Creating an Ocean Plug-in Test Project


The Plug-in Test Project is used for unit testing an existing Ocean Plug-in through the Ocean
Testing Framework. Before starting to write the unit tests, Ocean Testing Framework demands
several configuration steps in order to create a test project, as follows:

93

The test project has to contain a reference to the assembly of the plug-in to be tested;

The test project assembly has to be named with the same assembly name of the plug-in
to be tested plus the suffix .Test. Example: if the assembly name of the plug-in to be
tested is MyCompany.MyPlugin, then the test assembly name must be
MyCompany.MyPlugin.Test;

The test project output path (destination where assembly and compilation artifacts are
stored) must be set to Petrel installation folder;

Appendix
The Ocean Wizard

Reference paths must be pointed to Petrel installation and Public


(PETREL_HOME/Public) folders as well as to any additional required folder;

A reference to the Ocean Testing Framework assembly (Slb.Ocean.Petrel.Testing.dll)


must be added to the test project;

The Petrel configuration file (petrel.exe.config) must be copied into test project,
renamed with the same test project assembly name (Ex.:
MyCompany.MyPlugin.Test.dll.config), and have its property Copy to Output Directory to
Copy always;

Add references to assemblies of the used unit testing framework (NUnit).

Note: Due Petrel implementation restrictions, the Ocean Testing Framework supports only
NUnit as test framework.
There is clearly a big time consuming and manual effort only for configuring a test project. To
overcome such overhead and to boost the developer productivity, the Ocean Plug-in Test Project
wizard wraps up all of the above steps in a few clicks. In a solution containing the plug-in project
to be tested:
1. Click on File > New > Project;
2. Under Ocean templates, select Ocean Plug-in Test, provide a
project name and mark the option Add to solution;

Ocean
Template

Add the project to the current


solution

Figure 56: New Plug-in Test Project wizard launch

94

Appendix
The Ocean Wizard

3. Click on OK button;
4. In the next screen, select which project will be tested as well as
the NUnit installation folder. Note that only Ocean Plug-in
projects are listed in the combo box;

Ocean Plug-in projects list

NUnit Installation folder

Figure 57: Plug-in Test Project configuration

5. Click on Next button;


6. In the next screen, review the test project settings and click on
Finish button.

Figure 58: Plug-in Test Project settings review page

95

Appendix
The Ocean Wizard

7. A new Plug-in Test Project is created, including all of its required


configuration, a test setup class and a test template class.

Figure 59: Plug-in Test Project review settings page

8. After the project files have been created, the developer can
start coding his unit test against the plug-in to be tested.

96