Skip to content

No suitable parent found when applying transparency transform "hack" #127

Open
@t03i

Description

@t03i

I am trying to add a transparency layer to my displayed structure by copying the implementation in alphafold-transparency.ts and adapting it to my code structure.
When applying the transforms to a structure, the operation fails with the error "No suitable parent found".
Using the select, highlight, or other visual methods works just fine.

Do you have a pointer on how I can make it work?
Is there a specific order of operations I am missing or a different way to reference parents I must add?

Thank you very much in advance!

Tech Stack

I am using:

  • Svelte
  • PDBe-Molstar-component 3.3.2
  • Molstar 4.10.0

Reproduction Steps

  1. Initialize PDBe-MolStar viewer with an AlphaFold structure
  2. Attempt to apply confidence visualization via applyConfidenceVisualization()
  3. The operation fails with error: "No suitable parent found for 'transparency-{parentRef}'"

Code Snippets

export class MolstarWrapper {
  private viewer: any;

  constructor(viewerElement: any) {
    this.viewer = viewerElement;
  }


  async applyConfidenceVisualization() {
    await this.whenReady();

    const plugin = this.plugin;
    if (!plugin) {
      console.warn("No transparency plugin found");
      return;
    }

    const pLDDT = 70;
    const transparency = 1;

    const assemblyRef =
      this.plugin.managers.structure.hierarchy.current.structures[0].cell
        .transform.ref;
    const structure =
      plugin.managers.structure.hierarchy.current?.refs.get(assemblyRef);
    if (!structure) {
      console.warn("No structure found");
      return;
    }

    return plugin.dataTransaction(
      async (ctx: any) => {
        const loci = this.viewer.viewerInstance.getLociByPLDDT(pLDDT);
        await this.setStructureTransparency(
          plugin,
          structure.components,
          transparency,
          loci,
        );
      },
      { canUndo: "Apply Transparency" },
    );
  }

  private getFilteredBundle(
    layers: Transparency.BundleLayer[],
    structureRef: Structure,
  ) {
    const transparency = Transparency.ofBundle(layers, structureRef.root);
    const merged = Transparency.merge(transparency);
    return Transparency.filter(
      merged,
      structureRef,
    ) as Transparency<StructureElement.Loci>;
  }

  private async updateRepresentations(
    plugin: PluginContext,
    components: StructureComponentRef[],
    callback: TransparencyEachReprCallback,
  ) {
    const state = plugin.state.data;
    const update = state.build();

    for (const c of components) {
      for (const r of c.representations) {
        const transparency = state.select(
          StateSelection.Generators.ofTransformer(
            StateTransforms.Representation
              .TransparencyStructureRepresentation3DFromBundle,
            r.cell.transform.ref,
          ).withTag(TransparencyManagerTag),
        );

        await callback(update, r.cell, transparency[0]);
      }
    }

    update.commit();
  }

  private async setStructureTransparency(
    plugin: PluginContext,
    components: StructureComponentRef[],
    value: number,
    loci: StructureElement.Loci,
  ) {
    await this.updateRepresentations(
      plugin,
      components,
      async (update, repr, transparencyCell) => {
        const structure = repr.obj!.data.sourceData;
        if (Loci.isEmpty(loci) || isEmptyLoci(loci)) {
          return;
        }

        const layer = {
          bundle: StructureElement.Bundle.fromLoci(loci),
          value,
        };

        if (transparencyCell) {
          const bundleLayers = [
            ...transparencyCell.params!.values.layers,
            layer,
          ];
          const filtered = this.getFilteredBundle(bundleLayers, structure);
          update.to(transparencyCell).update(Transparency.toBundle(filtered));
        } else {
          const parentRef = repr.transform.ref;
          const parentNode = plugin.state.data.tree.transforms.get(parentRef);
          if (!parentNode) {
            throw new Error(`Parent node ${parentRef} not found in state tree`);
          }

          // Create the transparency transform params
          const filtered = this.getFilteredBundle([layer], structure);
          const transparencyRef = `transparency-${parentRef}`;
          const params = {
            ...Transparency.toBundle(filtered),
            parent: parentRef,
          };
          update
            .to(parentRef)
            .apply(
              StateTransforms.Representation
                .TransparencyStructureRepresentation3DFromBundle,
              params,
              {
                tags: TransparencyManagerTag,
                ref: transparencyRef,
              },
            );
        }
      },
    );
  }

Since I use Svelte, I have to use the web component:

<pdbe-molstar
      style="height: 100%; width: 100%; z-index: 4;"
      bind:this={viewerElement}
      custom-data-url={structureUrl}
      custom-data-format={format}
      custom-data-binary={binary}
      expanded={false}
      pdbe-logo={false}
      domain-annotation={true}
      hide-controls={true}
      sequence-panel={false}
      alphafold-view={true}
    >
</pdbe-molstar>

Expected Behavior

Set the transparency for individual residues and keep the pLDDT-based coloring

Actual Behavior

Display the structure with pLDDT-based coloring and fail with:

Error: No suitable parent found for 'transparency-etNZCwaao0fWvB2reMaljA'
    i pdbe-molstar-component.js:25
    J pdbe-molstar-component.js:25
    A pdbe-molstar-component.js:25
    _updateTree pdbe-molstar-component.js:25
    updateTree pdbe-molstar-component.js:25
    p pdbe-molstar-component.js:25
    u pdbe-molstar-component.js:25
    run pdbe-molstar-component.js:25
    runTask pdbe-molstar-component.js:25
    commit pdbe-molstar-component.js:25
    updateRepresentations MolstarWrapper.ts:300
    setStructureTransparency MolstarWrapper.ts:309
    applyConfidenceVisualization MolstarWrapper.ts:255
    transaction pdbe-molstar-component.js:25
    p pdbe-molstar-component.js:25
    u pdbe-molstar-component.js:25
    run pdbe-molstar-component.js:25
    runTask pdbe-molstar-component.js:25
    dataTransaction pdbe-molstar-component.js:25
    applyConfidenceVisualization MolstarWrapper.ts:252
    ...

Even though:

  1. The parent reference exists in the state tree (verified via logging)
  2. The parent node is accessible and valid
  3. The transform parameters include the correct parent reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions