I am trying to superimpose a PDB file into a 3D plot of points extracted from the PDB model, while making the PDB somewhat transparent for easy viewing of plotted points.

My problems are as follows.
-The scale of the PDB does not match my 3D plot range (RescalingTransform did not seem to work on the PDB object).
-Opacity does not seem to work on the PDB object.

My code first plots the data points extracted from the position of 3 atoms (the XYZ coordinates are take directly from the .pdb file.

(* Atom Positions *)
DNA1 := {0.107, 9.352, -1.508}              
DNA2 := {-0.696, 12.374, 138.546}
DNA3 := {-5.485, 1.769, 200.290}
DNApoints = {DNA1, DNA2, DNA3};

Each point represents the atoms at which a Dye label with a 6 carbon linker strand is attached to a real physical DNA strand matching this .pdb sequence. This linker molecule is flexible enough to allow the Dye label to potentially occupy multiple positions around the DNA atom to which it is attached. To represent this, I added some pretty spheres that enclose the space the label might be able to occupy.

(* Generate Sphere of Points and List of Colors to be used later*)
lColrs = {Darker[Magenta], Darker[Green], Darker[Red]};
lp := Normalize /@ RandomReal[{-1, 1}, {1*10^3, 3}];

I then use the above to generate a Graphics3D object out of several primitives. The three atom positions extracted from the PDB, three pretty spheres of points centered at each atom position and scaled to the length of a 6 carbon alkane chain. And finally, a triangle between the points to aid the eye.

DNAPntsTh := Graphics3D[
 {Opacity[0.15, Magenta], Translate[Point[7*lp], DNA1]},
 {Opacity[0.1, Darker[Green]], Translate[Point[7*lp], DNA2]},
 {Opacity[0.1, Red], Translate[Point[7*lp], DNA3]},
 {Opacity[0.06, Blue], Polygon[{DNA1, DNA2, DNA3}]},
 Thread[{lColrs, Point /@ DNApoints}, Antialiasing -> True]}
 }, Axes -> True, AxesLabel -> {"X", Y, Z}

Plot of Points

I then load the .pdb file

DNApdb = Import["https://pastebin.com/raw/UPk5Gf1z",
                {"PDB", "Graphics3D"}, "Rendering" -> "BallAndStick"]

DNA pdb

Okay, now for the issue at hand...

When I look at the .pdb by plotting or by using AbsoluteOptions[DNApdb, PlotRange], I find that the scale is waaayy off. So I attempted to use Rescaling transform to match up the ranges (not ideal in the first place as the atom positions from the 3D plot are not located at the extremes of the pdb and so therefore will not automatically match up without extra adjustment.)

Anyhow, the command does not seem to scale the image. I use AbsoluteOptions to get the two data ranges and then attempt to scale the .pdb to the data points.

AbsoluteOptions[DNAPntsTh, PlotRange]
AbsoluteOptions[DNApdb, PlotRange]
PntsThRsc = 
RescalingTransform[{{-1086.3, 1004.0}, {-1070.6, 1979.4}, {-161.6, 
 20161.9}}, {{-5.485, 0.107}, {1.769, 12.374}, {-1.508, 200.29}}];
RescaledPDB = PntsThRsc[DNApdb];

I hope I'm just using RescalingTransform incorrectly.

Also, attempts to make the pdb graphic object transparent using Opacity[] has failed to work in the way I am trying to implement it. I am also hoping that I am just trying to use it incorrectly.

Here is an example,

Show[{Opacity[0.3], DNApdb}]

Which will return an error saying that Opacity is not a Graphic Object. However attempting to combine this command with the .pdb using Graphics3D also returns an error.

I am grateful for whatever help I can get.

  • $\begingroup$ You cannot apply "directly" RescalingTransform and Opacity to DNApdb the way you do. DNApdb is a Graphics3D object, so you have to do the modifications "inside" it ... I'll give more explanations soon. But first, I don't understand why you try to rescale your dna molecule ? Do your 3 atoms coordinates (DNApoints) correspond exactly to 3 particular atoms in the pdb molecule ? Could you explain better "The Scale of the PDB does not match my 3D plot range" ? $\endgroup$
    – SquareOne
    Jun 24, 2015 at 22:36
  • $\begingroup$ You don't need := in most places you used it ... $\endgroup$
    – SquareOne
    Jun 25, 2015 at 1:24

1 Answer 1


The title of your post should be rather something like "Why Import rescales my pdb coordinates ?"

The answer is actually in the pdb documentation:

enter image description here

Yes, for some reason, when Mma imports a PDB file it automatically converts the atoms coordinates (by default in Angstroms) into picometers, and it explains why you observe a completely different PlotRange than expected. In other words, the coordinates have just been rescaled exactly by 100.

You can check that visually by importing the coordinates of your dna molecule (instead of the graphics):

Import["/path/to/your/dna1_fixed.pdb", "VertexCoordinates"] // First

returns the first coordinate of the molecule in the pdb file:

{10.7, 935.2, -150.8}

which corresponds to the first line of the pdb file:

ReadList["/path/to/your/dna1_fixed.pdb", String, 1]


 {"ATOM      1  P     C A   1       0.107   9.352  -1.508  1.00  0.00        P"}

This atom corresponds actually also to your DNA1 atom ... This is how I figured out what was the problem.

So, the simplest solution here I think is to convert your DNA1,DNA2,DNA3 atoms coordinates into picometers (x100), and everything will superimpose fine.

Here is what I get :

enter image description here

and concerning your opacity problem you can do:

enter image description here

(For the spheres, instead of Translate[Point[7*lp], DNA1] I did Sphere[DNA1, 700], and I imported the molecule with "Rendering" -> "Wireframe")


Here is the other solution which will you prevent you from rescaling the axes. Instead it rescales the imported pdb 3D graphics.

Your imported pdb graphics, DNApdb, is actually a Graphics3D object, which you can tell by running:



You can extract the graphics primitives which are used to build the graphics this way :

{Specularity[GrayLevel[1], 100], EdgeForm[None], AbsoluteThickness[1],
  GraphicsComplex[{{10.7, 935.2, -150.8}, {13.5, 
    1068.7, -214.6}, {96.7, 918.4, -31.5}, {-140.1, 
    896.3, -114.2}, {-222.3, 833.4, -214.4}, {-300., 718.7, -153.3},...

Here, the XYZ atoms coordinates are contained inside GraphicsComplex.

To rescale the XYZ:

DNApdbAngstrom = 
  DNApdb[[1]] /. 
   GraphicsComplex[xyz_, primitives_] -> GraphicsComplex[xyz/100, primitives]]
  • $\begingroup$ very nice! I somehow glossed over the picometer scaling in the PDB documentation. While I will try to rescale the axes into Angstroms for presentation, this makes a lot more sense now. Thank you! $\endgroup$
    – RyanR
    Jun 25, 2015 at 3:00
  • $\begingroup$ @RyanR See my edit for another solution which rescales the imported pdb graphics. $\endgroup$
    – SquareOne
    Jun 25, 2015 at 12:05
  • $\begingroup$ That's some slick coding. Thanks for this great example! $\endgroup$
    – RyanR
    Jun 26, 2015 at 2:48
  • 1
    $\begingroup$ Have you had issues with slow rendering on rotation when combining the graphics in Show[{DNApdb, DNAPntsTh}]? Is there a way to allocate more memory to this in Mathematica? I have tried using RotationAction->"clip" as suggesting in other posts on this topic. I have also taken out the := asignments and replaces them with = so that they are evaluated only once, but this did not noticeably change rendering speed during rotation. The rotation is taking nearly 10-20 seconds to actually move and is even occasionally freezing Mathematica. Any suggestions? $\endgroup$
    – RyanR
    Jun 26, 2015 at 13:25
  • $\begingroup$ I should add that individually, these objects rotate just fine. It is only when I Show them together that I have a problem. $\endgroup$
    – RyanR
    Jun 26, 2015 at 13:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.