PhET-iO Guide

Last update Wed Jan 31 2024 12:00:42 GMT-0700 (Mountain Standard Time)

Contents


PhET-iO Studio and the Standard PhET-iO Wrapper

PhET-iO Studio enables anyone to customize the starting state of the simulation. This guide will orient you to PhET-iO Studio capabilities, present several ways to customize a simulation, and share best practices for efficient workflow.

alt text "Overview of PhET-iO Studio" Figure 1: The PhET-iO Studio Environment

The PhET-iO Studio consists of four panels, labeled 1 to 4 in Figure 1:

  1. PhET-iO Simulation: Contains a live version of the simulation that can be interacted with to customize the starting state. The panel borders to the left and bottom can be used to resize the simulation.
  2. Studio Tree: Contains all of the PhET-iO Elements and has a hierarchical structure. Use the search bar at the top to find particular elements in the tree.
  3. Element Panel: Contains the name of the selected PhET-iO Element, its unique identifier (phetioID), and associated metadata. Some elements contain controls in this panel for customization.
  4. Studio Control Panel: Contains a variety of controls, tools, and links to documentation.

Workflow in PhET-iO Studio

Creating a New Standard PhET-iO Wrapper

PhET-iO simulations work within an html file called a wrapper. When using PhET-iO Studio, you will download your customization as a “Standard PhET-iO Wrapper”.

We recommend this general flow when creating a Standard PhET-iO Wrapper.

Tip!
Resize the PhET-iO simulation panel to be the same (or similar) aspect ratio as will be used in your end product before you start configuring Studio. Some simulations allow elements to float to the edges as the simulation resizes to maximize the space for student exploration. When loading a customized simulation, it will resize to fit the browser/iframe aspect ratio. As a result, elements may shift to remain in the visible bounds.

Loading an Existing Standard PhET-iO Wrapper for Revision, Migration, or Adaptation

The Standard PhET-iO Wrapper may be loaded into PhET-iO Studio for further editing, for forward migration to the next minor version of the simulation (e.g. 2.0 to 2.1), or for adaptation to make a new wrapper. Use the Load Button and select the file you wish to edit or migrate. For more information about migration, see Updating the Standard PhET-iO Wrapper via Studio.

Caution!
We recommend that you avoid editing the Standard PhET-iO Wrapper file after you have created it. Once edited, the file becomes a Custom PhET-iO Wrapper and may no longer reliably load in PhET-iO Studio for revision nor realize the benefits of migration support. Any additional customizations you have made will not be maintained through the loading process. Any additional customizations you require should be done via API commands coded outside of the Standard PhET-iO Wrapper.

Customizing the Simulation

You can customize the simulation in two ways: by interacting directly with the simulation or through the PhET-iO Studio Tree. The customized state will become the initial state of the simulation within the Standard PhET-iO Wrapper. The Reset All button will return the simulation to this customized state rather than the original default state.

Customization through Interaction

The simplest way to customize a simulation is through direct interaction with the simulation in PhET-iO Studio. For example, you can change initial values or turn features on/off using the controls in the simulation. You can also drag items around to create a custom starting configuration.

Customization Using the PhET-iO Studio Tree

Not all customizations are achievable through direct interaction with the simulation, such as completely hiding a control.

Understanding PhET-iO Elements

Simulations contain numerous PhET-iO Elements, each representing an object within the simulation, such as the voltage of a battery or the visibility of a checkbox. Instructionally important PhET-iO Elements are designated as “Featured” and the PhET-iO Studio Tree is filtered by default to only display the “Featured” elements.

Every PhET-iO Element has a unique identifier called a phetioID. The phetioID reveals the hierarchy of the PhET-iO Element within the Studio Tree. For example, the phetioID of a “Values” checkbox within a simulation may appear like this:

simName.screenName.view.controlPanel.valuesCheckbox

The “Values” Checkbox appears within the controlPanel under the view of a particular screen (screenName) of the simulation (simName).

PhET follows a model/view software design pattern, and each screen is separated into a "model" and a "view". Model code is responsible for the simulation data and logic, such as the value of a slider or the position of a projectile in meters. View code is responsible for visual representation, including the user interface, such as the slider label or visibility. For convenience, view elements generally contain links to the corresponding model elements, which are indicated by the appearance of *property (in blue text) in the Studio Tree.

These linked properties point back to the PhET-iO Element where the value is actually stored. Unlike the PhET-iO Element itself, these are interim names and cannot be used for API calls. The Element panel for the linked property displays the target phetioID and embeds a preview of the target PhET-iO Element’s value and metadata for easy customization.

To easily discover the Elements in the Studio Tree that correspond to an item in the simulation, use the autoselect feature.

Groups of similar objects, such as the bunnies in the Natural Selection simulation (see bunnyGroup), are created from an “archetype”. Archetypes are the blueprint for how the PhET-iO Element is created. Individual Elements can be further customized and retain those customizations in state. The archetype shows the pattern of the PhET-iO Element names in the tree, but the archetype itself is not hooked up to any actual data or objects in the simulation. The objects created from the archetype will appear below it in the tree.

Dialogs are created from a PhetioCapsule. To customize a dialog, it must first be opened. The dialog will appear in the Studio Tree, nested under the capsule in the Studio Tree.

General Customizations

These are customizations that are frequently used during instructional design and apply to any simulation.

Remove a screen, change screen order, or set the selected screen

To provide learners with access to only a subset of a simulation’s screens and/or to change the order of screens in the navigation bar, use centerAndVariability.general.model.screens.availableScreensProperty

To remove students' ability to navigate between screens by hiding the screen icons in the navigation bar, use centerAndVariability.general.model.screens.isUserNavigableProperty

To set which screen is selected in the simulation, use centerAndVariability.general.model.screens.selectedScreenProperty

To disable external links, set allowLinksProperty to false.

centerAndVariability.general.model.allowLinksProperty

Disable Pan and Zoom feature

Using standard touch gestures, mouse controls, and keyboard shortcuts, diverse learners can zoom into any region of the sim to get as much detail as they need. To disable this feature set supportsPanAndZoomProperty to false.

centerAndVariability.general.view.display.supportsPanAndZoomProperty

Common Patterns of Customization

There are some customizations that will follow a similar pattern in all simulations. These are described below.

Text String Customization
Preferences Customization

Each PhET-iO Simulation includes a Preferences dialog, which can contain tabs such as Overview, Simulation, Visual, Audio, Input, and Localization.

Some preference selections are saved into the simulation state and persist in the save and launch process of the Standard PhET-iO Wrapper. These include audioEnabledProperty, colorProfileProperty, localeProperty, and all settings on the Simulation tab.

Many preference selections - generally those that are learner-specific modality preferences - are not instrumented and therefore will not be saved in the simulation state. In this way, if the simulation state is saved and used in a general context, the learner-specific modality preferences are not inadvertently exposed in a classroom setting. This protects learner privacy.

Launch Sim with Audio Muted (if sound is supported)

By default, audio is enabled. To mute the audio, set audioEnabledProperty to false. centerAndVariability.general.view.audioManager.audioEnabledProperty

Remove All Audio (if sound is supported)

To completely disable all audio in the simulation and remove students’ ability to turn audio back on requires 3 customizations.

Launch Sim Optimized for Projection Screen

Simulations with a dark background often have a Projector Mode for better contrast when projecting the simulation in a classroom. Set the colorProfileProperty to projector. centerAndVariability.general.view.colorProfileProperty

Set Default Language (Locale) of the Standard PhET-iO Wrapper

PhET simulations are translated into many languages (locales). The choices under the localeProperty will identify all of the locales for which a translation is available. Set the locale you want the Standard PhET-iO Wrapper to use as its default locale. See below for more information about changing locale from within your product. centerAndVariability.general.model.localeProperty

Hide All Preferences or a Subset of Preferences Tabs

To prevent access to all Preferences, hide the preferencesButton. centerAndVariability.general.view.navigationBar.preferencesButton.visibleProperty

To prevent access to individual categories of Preferences, hide the associated tab. For example, the Localization tab can be hidden with centerAndVariability.general.view.navigationBar.preferencesButton.preferencesDialogCapsule.preferencesDialog.preferencesTabs.LocalizationTab.visibleProperty

As a reminder, dialogs must first be opened before they can be customized. The above phetioID will not exist until the Preferences dialog is opened.

Simulation-specific Customizations

For simulation-specific customization examples, refer to the Examples document.

Special Case!
In some specific cases, query parameters need to be used to customize the simulation. For example, a starting population of bunnies in the Natural Selection simulation is configured by a query parameter.

Limitations to Customizing State

While almost all aspects of a simulation's behavior are saved as part of the state configuration, there are a few limitations. The following aspects are not generally saved in the PhET-iO state:

Using and Testing the Standard PhET-iO Wrapper in Your Product

The Standard PhET-iO Wrapper is the easiest way to launch a customized PhET-iO simulation. It can be used entirely on its own by opening it in a browser, or it can be uploaded into your content management system or product to help track its use and version. The most common product configuration is using an iFrame in the product that loads the Standard PhET-iO Wrapper file.

The Standard PhET-iO Wrapper can also be used as a source of data in conjunction with a Custom PhET-iO Wrapper, as described here.

Use of Query Parameters with the Standard PhET-iO Wrapper

Two query parameters are supported for use after PhET-iO Studio has generated the Standard PhET-iO Wrapper: locale and phetioDebug.

The locale query parameter can be used to support language (locale) switching of the simulation used in the Standard PhET-iO Wrapper. In your product, append ?locale=es to the URL of the Standard PhET-iO Wrapper file to, for example, start up the customized simulation in Spanish. This works even if you saved your wrapper in English, as long as the Spanish locale is available in the translation set.

If you specify a locale for which a translation does not exist, the locale query parameter is ignored and the simulation will retain the localeProperty used when creating the Standard PhET-iO Wrapper.

The phetioDebug query parameter is used with the Standard PhET-iO Wrapper for quality assurance testing as described in the next section.

Caution!
While standard PhET simulations available at phet.colorado.edu leverage a number of query parameters to achieve some basic customizations, these query parameters are not supported for use with the Standard PhET-iO Wrapper.

Quality Assurance Testing in Your Product

By default, the simulation runs in debug mode when opened in PhET-iO Studio (indicated by the red underline under the PhET-iO logo). This means that the PhET-iO simulation is loaded with lower tolerance for exposing errors (via the javascript console provided by a browser's developer tools). In this mode, problems are easier to discover. However, debug mode is turned off by default in the Standard PhET-iO Wrapper, since it is to be used in student-facing production code. We recommended re-enabling debug mode when conducting your own quality assurance testing of the customized simulation in your product by adding ?phetioDebug=true as a query parameter onto the end of the wrapper URL, when running the Standard PhET-iO Wrapper.

Using Standard PhET-iO Wrappers as Data for a Custom PhET-iO Wrapper

If you are developing a templated Custom PhET-iO Wrapper (such as a lab notebook widget), the Standard PhET-iO Wrapper can be used as a data source by leveraging its structure to extract the start-up configuration of the simulation, and using this data to launch the sim with your generic Custom PhET-iO Wrapper. PhET provides a template for a Custom PhET-iO Wrapper, which includes code showing how to realize this approach, see Creating a Custom PhET-iO Wrapper. By leveraging the Standard PhET-iO Wrapper in this way, you empower instructional designers to do the customizations, reduce developer resource use, and leverage the save, load, revision, and migration capabilities of PhET-iO Studio.

// on an already launched sim . . .
const myStandardWrapperHTML = await myClient.getStandardPhetioWrapperHTML();

You can create a PhetioClient specifically for loading a Standard PhET-iO Wrapper state:

const myStandardWrapper = await fetch( './myStandardWrapper.html' );
const htmlText = await myStandardWrapper.text();
const simFrame = document.getElementById( 'sim' );
const phetioClient = await phetio.PhetioClient.createFromStandardPhetioWrapper( simFrame, htmlText );
await phetioClient.invokeAsync( 'phetioEngine', 'displaySimulation' );

More complex cases can take control of the launch sequence:

const myStandardWrapper = await fetch( './myStandardWrapper.html' );
const htmlText = await myStandardWrapper.text();
const simFrame = document.getElementById( 'sim' );
const phetioClient = new phetio.PhetioClient( simFrame );
phetioClient.launchSimulation( {
  displaySim: false,
  onSimInitialized: async function() {

    // Load the Standard PhET-iO Wrapper customizations into the running sim.
    await phetioClient.loadStandardPhetioWrapperFromHTML( htmlText );

    // Display the sim after setting these customizations to prevent a startup "flicker".
    await phetioClient.invokeAsync( 'phetioEngine', 'displaySimulation' );
  }
} );

This type of reusable Custom PhET-iO Wrapper development will require the support of a skilled software development team, and is described in more detail in the next section.

Creating a Custom PhET-iO Wrapper

A PhET-iO wrapper embeds a PhET-iO simulation and leverages the PhET-iO API and feature set. The wrappers on the index page demonstrate the PhET-iO API and features for this simulation, and can be used as examples to begin new wrapper development. At the bottom of index page there is a code block with the Custom PhET-iO Wrapper template, which can be used for beginning your own custom wrapper development.

A good place to start is by downloading the Custom PhET-iO Wrapper template and launching it on your development machine. Try printing messages to the console from the onEvent callback. Once that is working, you can start using phetioClient.invoke to send commands to the simulation. All necessary globals like PhetioClient, are imported from the file phet-io.js.

For more information about the capabilities of launchSimulation, refer to the LaunchSimulationOptions API documentation.

A Custom PhET-iO Wrapper that can load any Standard PhET-iO Wrapper

To develop a Custom PhET-iO Wrapper that can load a Standard PhET-iO Wrapper from a different sim or different version, you can use replaceStaticClient like so:

const PhetioClient = await phetio.PhetioClient.replaceStaticClient( myStandardWrapperHTML );
const phetioClient = await PhetioClient.createFromStandardPhetioWrapper( simFrame, myStandardWrapperHTML );

To dynamically switch between different Standard PhET-iO Wrappers at runtime, you need to dispose the previous PhetioClient instance:

// The "PhetioClient1" variable overrides the global phetio.PhetioClient
const PhetioClient1 = await phetio.PhetioClient.replaceStaticClient( myStandardWrapperHTML1 );
const phetioClient = await PhetioClient1.createFromStandardPhetioWrapper( simFrame, myStandardWrapperHTML1 );
phetioClient.dispose();

const PhetioClient2 = await PhetioClient1.replaceStaticClient( myStandardWrapperHTML2 );
const phetioClient2 = await PhetioClient2.createFromStandardPhetioWrapper( simFrame, myStandardWrapperHTML2 );

Please be aware that the original phetio.PhetioClient remains and should not be used with the new Standard PhET-iO Wrapper. Here is an example that uses this process to select a standard PhET-iO wrapper via a query parameter:


<html>
<body>
<iframe id="sim" width="1024" height="668"></iframe>

<script src="https://phet-io.colorado.edu/sims/center-and-variability/1.2.0-dev.1/phet-io/lib/phet-io.js"></script>

<script>

  const simFrame = document.getElementById( 'sim' );

  ( async () => {

    // Load a standard PhET-iO wrapper
    const url = new URLSearchParams( window.location.search ).get( 'url' );
    const myStandardWrapper = await fetch( `./${url}` );
    const htmlText = await myStandardWrapper.text();

    // Create the new PhetioClient
    const PhetioClient = await phetio.PhetioClient.replaceStaticClient( htmlText );

    // Launch the sim
    const phetioClient = await PhetioClient.createFromStandardPhetioWrapper( simFrame, htmlText );

    // Example invoke call
    const phetioIDs = await phetioClient.invokeAsync( 'phetioEngine', 'getPhetioIDs' )
    console.log( phetioIDs.length, phetioIDs );
  } )();
</script>
</body>
</html>

Updating to a Newer Version

PhET-iO releases simulation updates for many reasons, including:

A PhET-iO simulation consists of two distinct layers.

  1. The wrapper communication layer defines a protocol for launching and communicating with the simulation. That documentation is described here in the API docs. Like a conventional software project, changes to this layer will be accompanied by a list of breaking changes to help update your usages. It is a PhET-iO implementation goal to minimize breaking changes in this layer to reduce the development burden on PhET-iO clients.

  2. The simulation layer defines the PhET-iO Elements and the methods that can be called on them, as well as the arguments which may be passed to the method. A PhET-iO simulation may have thousands of PhET-iO Elements, so the process of providing a list of breaking changes and requiring the client to update numerous sites is much more complex. Therefore, we provide additional support at this level to streamline the process in this layer.

Updating the Standard PhET-iO Wrapper via Studio

When a Standard PhET-iO Wrapper is saved from Studio, it can be loaded back into that version of Studio and into Studio of the next minor version of that simulation. (Studio cannot load save files from later versions.) We call this "migration." For example, a Standard PhET-iO Wrapper customized from Gravity and Orbits 1.5 can be loaded into Studio of Gravity and Orbits 1.6. When Studio loads a simulation from a supported prior version, it will carry those customizations into the next version. In some cases, a customization may be unsupported in the new version. In that case it will be well documented when migrating.

Updating Many Standard PhET-iO Wrappers Programmatically

To update many Standard PhET-iO Wrappers, you may use the phetio.PhetioClient.createFromStandardPhetioWrapper in a loop like so:


<html>
<body>
<iframe id="sim" width="1024" height="668"></iframe>

<!--Point this to the phet-io.js lib for that sim.-->
<script src="https://phet-io.colorado.edu/sims/center-and-variability/1.2.0-dev.1/phet-io/lib/phet-io.js"></script>
<script>

  const simFrame = document.getElementById( 'sim' );

  ( async () => {
    for ( let i = 0; i < 5; i++ ) {

      // Load the text
      const myStandardWrapper = await fetch( `./center-and-variability(${i}).html` );
      const htmlText = await myStandardWrapper.text();

      // Create a phetioClient compatible with that version
      const phetioClient = await phetio.PhetioClient.createFromStandardPhetioWrapper( simFrame, htmlText );

      // Output it as a Standand PhET-iO Wrapper
      const string = await phetioClient.getStandardPhetioWrapper();

      // Save it to disk
      const blob = new Blob( [ string ], { type: 'text/plain;charset=utf-8' } );
      window.phetio.saveFile( blob, `migrated-wrapper-${i}.html` );

      phetioClient.dispose();
    }
  } )();
</script>
</body>
</html>

Adjust this loop to access the wrappers you want to automatically migrate. Run this script from an http server (will not work from file://).

Updating a Custom PhET-iO Wrapper

Currently, upgrading a Custom PhET-iO Wrapper is a manual process, unlike Standard PhET-iO Wrapper upgrades. Please see the API Overview to better understand PhET-iO versioning and API stability. PhET-iO technical support is available. Please reach out to the PhET-iO team.

Self-Hosting and Offline Usage

Self-Hosting PhET-iO Simulations

In some circumstances, it may be necessary for a PhET-iO Client to self-host the PhET-iO Simulations and Wrapper Library. For example, if the PhET-iO Application must be run on a network that can access the PhET-iO Client server, but not phet-io.colorado.edu. In this case, please follow these steps:

Please be aware that self-hosting PhET-iO Simulations makes it impossible to automatically receive maintenance releases, so should only be used as a last resort.

Offline Usage

It is also possible to use PhET-iO simulations and Custom PhET-iO Wrapper files offline. For example, in classrooms that do not have any internet access, the sims can still be prepared for usage like so:

As above, please be aware that offline PhET-iO simulations cannot automatically receive maintenance updates, and therefore usage from the phet-io.colorado.edu site is recommended where possible. Also, please be aware of the terms of the license agreement that constrain how PhET-iO files are permitted to be redistributed.

User Interaction Data in PhET-iO Simulations

PhET-iO simulations can be configured to output a backend data stream in JSON format for data analytics. Reach out to the development team for more information.

More Details