Material Library
The material library is the database of available materials which may be assigned to layers in geometrical model, allowing for a simulation to be run.
Treble's material library contains a variety of different materials organised by category.
The materials in the Treble database are all either based on measurements or on empirical models of the material assemblies, with the exception of materials included in the Other
category.
All materials in the library possess both random-incidence absorption coefficients and complex reflection coefficients, as well as a default scattering value.
You can print the available categories using the following code snippet:
material_library = tsdk.material_library.get_categories_with_count()
dd.as_table(material_library)

The count included in this table includes both the materials included by default with the SDK's installation, as well as any Imported Materials added to the library by members of your organisation. To access the Material Library while excluding orgainzation-generated materials, you may use the code in Example 1.
Methods
material_library.search
Searches for a material with a name or portion of a name containing the given string.
The search function is not case sensitive, and returns substring results. If you can't recall the full name of the material, the search function will return results with the portion of the name you provide.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
name | string | Name of material to search for. | 'Wood' ,'woo' |
Returns
List[MaterialDto]
- A list of MaterialDto objects.
Examples
# Search for materials with 'Gypsum' in the name.
materials = tsdk.material_library.search(name='Gypsum')
assert materials
dd.as_table(materials)
# The search function does not care about upper- or lower-case letters.
materials2 = tsdk.material_library.search(name='GYPSUM')
assert len(materials) == len(materials2)
# You can also search for substrings.
materials = tsdk.material_library.search(name='ypsum')
assert len(materials) == len(materials2)
material_library.get
Fetches materials available in the library. If the optional category parameter is not specified, the function fetches all materials in the library.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
category | MaterialCategory or string | Optional parameter to filter the fetched results with. | category='Porous' , category=treble.MaterialCategory.gypsum |
Returns
List[MaterialDto]
- A list of MaterialDto objects.
Examples
# get all available materials
all_materials = tsdk.material_library.get()
dd.as_table(all_materials)
# get all materials within a certain category using a MaterialCategory
gypsum = tsdk.material_library.get(category=treble.MaterialCategory.gypsum)
# get all amterials within a certain category using a string
porous = tsdk.material_library.get(category= 'Porous')
material_library.get_by_name
Fetches a specific material by its name.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
id | string | The unique material name. | 'Gypsum board nailed to studs' |
Returns
MaterialDto
- The MaterialDto object associated with the material name.
Example
wall = tsdk.material_library.get_by_name('Gypsum board nailed to studs')
material_library.get_by_id
Fetches a specific material by its unique identifier.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
id | string | The unique material id hash. | '6981aefb-9d76-4498-8c9f-83aeb133d827' |
Returns
MaterialDto
- The MaterialDto object associated with the material ID.
This function is especially useful if you have created materials with duplicate names. For instance, if your organisation's existing absorption coefficient libraries contain duplicate values for "25mm thick fiberglass board" and both have been imported into your Material Library, using the material ID will ensure that you always select the version you wish.
Example
wood_floor = tsdk.material_library.get_by_id('6981aefb-9d76-4498-8c9f-83aeb133d827')
material_library.get_categories
Fetches a list of the available material categories.
Arguments
None.
Returns
List[str]
- List of available material categories as string.
Example
print(tsdk.material_library.get_categories())
material_library.get_categories_with_count
Fetches a list of the available material categories, along with a summary of the number of materials in each category.
Arguments
None.
Returns
List[CategoryInfoDto]
- List of CategoryDto
objects.
Example
material_library = tsdk.material_library.get_categories_with_count()
dd.as_table(material_library)
material_library.perform_material_fitting
Fit a new Treble material to user-provided material inputs. See Import Materials.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
material | MaterialDefinition | The MaterialDefinition created by the user. |
Returns
MaterialDto
- A MaterialDto object associated with the fitted material.
The MaterialDto
object created by this method has not yet been permanently added to the Material Library! To add it to the library, you must pass the output of this function to the material_library.create()
function.
Example
# Create the material definition object
material_definition = treble.MaterialDefinition(
name="Material from reflection coefficient",
description="Imported material",
category=treble.MaterialCategory.curtains,
default_scattering=0.4,
material_type=treble.MaterialRequestType.reflection_coefficient,
coefficients=reflection_coefficients
)
# Material fitting, nothing is saved in this step
fitted_material = tsdk.material_library.perform_material_fitting(material_definition)
material_library.create
Add a fitted material to the Treble Material Library.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
material | MaterialDto | The fitted material object returned by perform_material_fitting |
Returns
MaterialDto
- The MaterialDto object added to the Material Library.
Example
# Add the fitted material to the library
created_material = tsdk.material_library.create(fitted_material)
material_library.delete
Remove a material from the material library.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
material | MaterialDto or material id string | The material object or the ID of the material to be deleted. | created_material |
Returns
bool
- True if the material has been successfully deleted.
Example
tsdk.material_library.delete(created_material)
Objects
MaterialDefinition
An object used by the Material Engine to fit a new Treble material to user-defined input values.
Arguments
Property | Type | Description | Example value |
---|---|---|---|
name | string | The human-friendly material name. | 'Acoustic plaster 68 mm thick' |
description | string | Additional information associated with the material. | 'Acoustic plaster with thickness of 50-70 mm' |
category | string | The category to which the material will be assigned. | 'Gypsum' |
defaultScattering | float | A single value numeric float between 0 and 1 used within the geometrical acoustics solver. | 0.15 |
materialType | enum | Type of input expected by the fitting engine. | treble.MaterialRequestType.full_octave_absorption , treble.MaterialRequestType.third_octave_absorption , treble.MaterialRequestType.surface_impedance , treble.MaterialRequestType.reflection_coefficient |
coefficients | array | The array of 8 or 24 elements (full-octave or third-octave) used in the material fitting | [0.2, 0.45, 0.3, 0.65, 0.8, 0.82, 0.84, 0.88] |
specificImpedance | bool | Only available when the materialType is treble.MaterialRequestType.surface_impedance | True, False |
All values must be provided when creating a MaterialDefinition
, except for the specificImpedance, which is only required when the materialType is surface_impedance
.
MaterialDto
An object containing information about a material contained in the database.
Property | Type | Description | Example value |
---|---|---|---|
id | string | A unique alpha-numeric identifier of the material. | 'b9f93015-8519-4b7e-898e-cb7efd845f3d' |
name | string | The human-friendly material name. | 'Wood' |
description | string | Additional information associated with the material. | '50 mm thick wood' |
absorptionCoefficients | list | The random-incidence absorption coefficients associated with the material, defined at 8 octaves. | [0.16, 0.15, 0.12, 0.09, 0.08, 0.08, 0.08, 0.07] |
category | string | The category which the material belongs to. | 'Wood' |
materialJson | string | JSON containing information regarding the material fitting. | |
materialMetadataJson | string | JSON containing information regarding the fitted material's properties. | |
defaultScattering | float | A single value numeric float used within the geometrical acoustics solver. | 0.25 |
userId | string | Identifier of user that created this material if it was user-created. | 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' |
organizationId | string | Provided if material is owned by an organization. | 'ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj' |
The JSON files contain archival information about the Treble material, which are generally not needed for typical use-cases. However, you can retrieve the real and imaginary portions of the complex reflection coefficients with the following example code.
Example
import json
wood_floor = tsdk.material_library.get_by_id('6981aefb-9d76-4498-8c9f-83aeb133d827')
wood_floor_json = json.loads(fitted_material.materialMetadataJson)
wood_floor_refl = np.asarray(wood_floor_json['RealReflectionCoefficient']) + \
1j * np.asarray(wood_floor_json['ImagReflectionCoefficient'])
MaterialAssignment
A MaterialAssignment
object is used to assign materials to specific layers within the geometrical model and is a necessary step in defining a simulation.
Property | Type | Description | Example value |
---|---|---|---|
layerName | string | The geometry's layer name that will receive the material. | layer_name="shoebox_walls" |
material | materialDto | The desired MaterialDto to assign to the layer. | material=wood_floor |
scatteringCoefficient | float | List[float] | None | The scattering coefficient to assign to the layer, either a single number or an array of 8. | scattering_coefficient=0.1 |
While creating the MaterialAssignment object, a new scattering coefficient may be provided as either a single-number value, or an array of 8 values between 0 and 0.99.
If no scattering coefficient is included in this step, the material's default scattering coefficient will be used in GA simulations.
You may retrieve the default scattering coefficient from the material using some_material.defaultScattering
.
Example
# define a wood floor material, using get_by_id
wood_floor = tsdk.material_library.get_by_id('6981aefb-9d76-4498-8c9f-83aeb133d827')
# define a gypsum-board wall material, using get_by_name
walls = tsdk.material_library.get_by_name('Gypsum board nailed to studs')
# reuse the gypsum board walls for the ceiling
ceiling = tsdk.material_library.get_by_name('Gypsum board nailed to studs')
# create a list of material assignments
# change the default scattering coefficient for the ceiling layer
material_assignment = [
treble.MaterialAssignment(layer_name="shoebox_walls",material=walls),
treble.MaterialAssignment(layer_name="shoebox_floor",material=wood_floor),
treble.MaterialAssignment(layer_name="shoebox_ceiling",material=ceiling,scattering_coefficient=0.1)
]
Alternatively, you can populate the list of MaterialAssignments in one line.
The following example gets a random material from Rigid category of the material lirbary, and assigns a new, random scattering coefficient for each layer in the model called room
.
import random
material_assignments = [
treble.MaterialAssignment(x, random.choice(tsdk.material_library.get(category=treble.MaterialCategory.rigid)), random.uniform(0,1)) for x in room.layer_names
]
Examples
Sort default materials from created materials
The following code sorts the materials contained with the library into a list of default materials and a list of all materials created or imported by members of your organization.
If your organization has not created any materials, the created_materials
list will be empty.
# Get all materials in the library
all_materials = tsdk.material_library.get()
# Get your user summary
overview = tsdk.get_overview()
# Isolate your organization's ID
id = overview.organizationId
# Prepare the lists
default_materials = []
created_materials = []
# Loop through all materials
for material in all_materials:
# Check if the organizationId is None
if material.organizationId is None:
# Add the material to the default_materials list
default_materials.append(material)
# Check if the organizationId matches your organization's ID
elif material.organizationId == id:
# Add the material to the created_materials list
created_materials.append(material)
# Display the materials created by your organization
dd.as_table(created_materials)
Create a curated, random material assignment list
The functions of the material library can be combined to create a material assignment list containing random selections from a list of prepopulated material options. The following example creates a random material assignment from lists of acceptable materials for any of the rooms contained in our database of meeting rooms.
import random
# Grab the meeting rooms dataset
meeting_rooms = tsdk.geometry_library.get_dataset(treble.GeometryLibraryDataset.meeting_room)
models = meeting_rooms
# choose a random meeting room
model = random.choice(models)
# Initialize an empty set to store unique layer names
unique_layer_names = set()
# Iterate over each model and add its layer names to the set
for model_tmp in models:
unique_layer_names.update(model_tmp.layer_names)
# alphabetize
unique_layer_names = sorted(unique_layer_names)
print(unique_layer_names)
# pre-approved material lists
acoustic = tsdk.material_library.get(category='Perforated panels')
ceiling = tsdk.material_library.get(category='Gypsum')
acoustic_tiles = tsdk.material_library.search('ceiling')
ceiling = ceiling + acoustic_tiles # expand list of ceiling materials to include the acoustic_tiles list
chairs = tsdk.material_library.search('chair')
concrete_wall = tsdk.material_library.search('concrete')
floor = tsdk.material_library.search("floor")
floor = floor + concrete_wall
door = tsdk.material_library.search('door')
light_wall = tsdk.material_library.get(category='Gypsum')
monitor = tsdk.material_library.get(category='Windows')
table = tsdk.material_library.search('wooden flooring')
window = tsdk.material_library.get(category='Windows')
# create a dictionary to associate layer names with material lists
material_lookup = {
"Acoustic": acoustic,
"Ceiling": ceiling,
"Chairs": chairs,
"Concrete wall": concrete_wall,
"Door": door,
"Floor": floor,
"Light wall": light_wall,
"Monitor": monitor,
"Table": table,
"Window": window
}
# create a random material assignment from the approved lists, and assign a random scattering coefficient
material_assignment = [
treble.MaterialAssignment(
x,
random.choice(material_lookup.get(x, light_wall)), random.uniform(0,1)) # Default to light_wall if no match is found
for x in model.layer_names
]
Create a dictionary of random material assignments meeting a criteria
Building off the previous example, the following example uses the functions previously defined to create a list of possible material assignments that, when considered within the room model, should create a reverberation time between a minimum and maximum value when estimated via Sabine's formula. When combined with correct layer naming conventions in the previous example, this example allows you to create large dictionaries of valid material assignments for use in Bulk Simulations.
min_rt = 0.5 # define range of acceptable RT values
max_rt = 1.0
desired_assignments = 20 # define the number of desired valid material assignments
# Grab the meeting rooms dataset
meeting_rooms = tsdk.geometry_library.get_dataset(treble.GeometryLibraryDataset.meeting_room)
models = meeting_rooms
# choose a random meeting room
model = random.choice(models)
# Initialize variables for Sabine estimates and material assignments
sabine_estimate = []
sabine_fband_estimate = []
sabine_estimates = []
valid_assignments = []
while len(valid_assignments) < desired_assignments:
# Generate random material assignments for the layers of the model
material_assignment = [
treble.MaterialAssignment(
x,
random.choice(material_lookup.get(x, light_wall)), random.uniform(0,1)) # Default to light_wall if no match is found
for x in model.layer_names
]
# Recalculate Sabine estimates using the new material assignments
sabine_fband_estimate = model.calculate_sabine_estimate(material_assignment)
sabine_estimate = np.mean(sabine_fband_estimate[1:-1]) # Average from 125 Hz to 4 kHz
#only store material assignments if they fall within the defined range
if min_rt <= sabine_estimate <= max_rt:
print(model.name, sabine_estimate)
valid_assignments.append(material_assignment)
sabine_estimates.append(sabine_estimate)
Modify an existing material assignment list
For models with a large number of layers, it may be more efficient to modify an existing list of material assignments rather than create a new one. The following code creates a material assignment, and then modifies certain entries without regenerating the whole list.
# define a wood floor material, using get_by_id
wood_floor = tsdk.material_library.get_by_id('6981aefb-9d76-4498-8c9f-83aeb133d827')
# define a gypsum-board wall material, using get_by_name
walls = tsdk.material_library.get_by_name('Gypsum board nailed to studs')
# reuse the gypsum board walls for the ceiling
ceiling = tsdk.material_library.get_by_name('Gypsum board nailed to studs')
new_ceiling = tsdk.material_library.get_by_name('Plywood panelling, 1 cm thick')
# create a list of material assignments
# change the default_1 scattering coefficient for the ceiling layer
material_assignment = [
treble.MaterialAssignment(layer_name="shoebox_walls",material=walls),
treble.MaterialAssignment(layer_name="shoebox_floor",material=wood_floor),
treble.MaterialAssignment(layer_name="shoebox_ceiling",material=ceiling,scattering_coefficient=0.1)
]
dd.as_table(material_assignment)
# designate your good material for replacements
goodmat = new_ceiling
# Create a list of the layer names which need to be re-assigned.
badlayer = ["shoebox_ceiling"]
# Iterate over the material_assignment
for material in material_assignment:
layer_name = material['layerName']
if layer_name in badlayer:
print(f"Layer {layer_name} is a bad layer. Updating material: {material}")
# Update the material to use the "good" material properties
material['materialId'] = goodmat.id
material['materialName'] = goodmat.name
dd.as_table(material_assignment)