Last update Wed Jan 31 2024 12:00:42 GMT-0700 (Mountain Standard Time)
Contents
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.
Figure 1: The PhET-iO Studio Environment
The PhET-iO Studio consists of four panels, labeled 1 to 4 in Figure 1:
phetioID
), and
associated metadata. Some elements contain controls in this panel for customization.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.
phetioDebug
mode during
your product’s quality assurance testing phase,
see Using and Testing the Standard PhET-iO Wrapper in Your Product
.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.
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.
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.
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.
Not all customizations are achievable through direct interaction with the simulation, such as completely hiding a control.
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.
Alt
(Option
on a Mac) and mouse over an item in the simulation to select the corresponding Element in
the Studio Tree.Shift
and Alt
(Option
on a Mac) and mouse over a string to find the corresponding StringProperty
in
the Studio Tree.Ctrl
and mouse over an item in the simulation to select the linked property of the corresponding Element
in the Studio Tree (if a linked property exists).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.
These are customizations that are frequently used during instructional design and apply to any simulation.
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
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
There are some customizations that will follow a similar pattern in all simulations. These are described below.
visibleProperty
: used to show/hide elementsenabledProperty
: used to enable/disable elementsinputEnabledProperty
: used to make elements unclickable/unmovablevisibleProperty
of the top-level element to
false. For example, a radio button group can be hidden using radioButtonGroup.visibleProperty
. There is no need to
hide each individual radio button within the group.Shift
and Alt
(Option
on a Mac) as you
mouse over the string you would like to edit. This will jump you to the corresponding StringProperty
in the Studio
Tree. Edit the value in the PhET-iO Element panel.centerAndVariability.general.model.localeProperty
. The
displayed StringProperty
value in the PhET-iO Element panel will update and can be customized for that locale.es_MX
to es
) and then English. The fallback locale sequence can be customized
using centerAndVariability.general.model.fallbackLocalesProperty
. We recommend that you
begin fallbackLocalesProperty
with the primary locale of your product (if something other than English).centerAndVariability.general.model.strings.centerAndVariability
. Again, change the locale
of the displayed string using the Localization tab within the Preferences Dialog or by
using centerAndVariability.general.model.localeProperty
.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.
By default, audio is enabled. To mute the audio, set audioEnabledProperty
to false
.
centerAndVariability.general.view.audioManager.audioEnabledProperty
To completely disable all audio in the simulation and remove students’ ability to turn audio back on requires 3 customizations.
audioEnabledProperty
to false
.
centerAndVariability.general.view.audioManager.audioEnabledProperty
visibleProperty
to false
.
centerAndVariability.general.view.navigationBar.audioToggleButton.visibleProperty
visibleProperty
to false
.
centerAndVariability.general.view.navigationBar.preferencesButton.preferencesDialogCapsule.preferencesDialog.preferencesTabs.audioTab.visibleProperty
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
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
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.
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.
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:
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.
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.
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.
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.
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.
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>
PhET-iO releases simulation updates for many reasons, including:
A PhET-iO simulation consists of two distinct layers.
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.
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.
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.
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://).
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.
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:
script src
in your Standard or Custom PhET-iO Wrapper(s)
from https://phet-io.colorado.edu/.../lib/phet-io.js
to point to the lib/phet-io.js on your PhET-iO Client server.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.
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:
https://phet-io.colorado.edu/.../lib/phet-io.js
to
point to ./lib/phet-io.js
(as a relative path).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.
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.