I have some points in EPSG:4326

-110.28879750 64.46310187 405.49938863
-110.28879359 64.46310086 405.45967110
-110.28880175 64.46310446 405.93823604
-110.28880245 64.46310258 405.48060850
-110.28880636 64.46310359 405.52032604
-110.28880940 64.46310630 405.84055342
-110.29016983 64.46359000 397.06282465
-110.29016273 64.46359705 397.17277374
-110.29016977 64.46359475 397.00624992
-110.29016760 64.46359646 397.05006178

and corresponding points in EPSG:2956

534209.97079435 7148811.23661946 405.66139508
534210.15978267 7148811.12655780 405.62167763
534209.76281723 7148811.52287611 406.10024237
534209.73147933 7148811.31341930 405.64261487
534209.54249101 7148811.42348096 405.68233234
534209.39265980 7148811.72409217 406.00255961
534143.35502320 7148864.89322788 397.22480162
534143.68792246 7148865.68172274 397.33475061
534143.35204638 7148865.42154142 397.16822677
534143.45456271 7148865.61384061 397.21203861

but if I convert an EPSG:4326 to a EPSG:2956 poing using pyproj I get a different result?

import pyproj

p1 = pyproj.Proj("+init=EPSG:4326")
p2 = pyproj.Proj("+init=EPSG:2956")

# first points
epsg4326_point = (-110.28879750,64.46310187,405.49938863)
epsg2956_point = (534209.97079435,7148811.23661946,405.66139508)

print "Source point", epsg4326_point
print "Target point", epsg2956_point
print 'Manually converted result (different): ', pyproj.transform(p1, p2, *epsg4326_point)
  • How did you determine your corresponding points in EPSG:2956?
    – Mike T
    Commented Aug 13, 2015 at 23:48
  • I used Photoscan and exported the point cloud in both projections. Commented Aug 14, 2015 at 0:23

2 Answers 2


You were are actually converting from EPSG:4917 (ITRF96), not EPSG:4326 (WGS84).

See the TRX online utility from NRCan to do this conversion:


Unfortunately you cannot use PROJ.4 to convert ITRF projections; see enhancement ticket #154.

If you were using WGS84 in place of ITRF96, then your steps with pyproj were fine. However, if you need ITRF96, then you need other tools until PROJ.4 is updated. Or you can apply an affine transform after, if your area is small, to shift them according to ITRF96.


NAD83(CSRS) (which is based on ITRF96(1997.0)) is not a simple transformation away from WGS84. It's anchored to the North American plate, which is rotating counter-clockwise, and uplifting -- in some places rapidly -- due to isostatic rebound. Proj doesn't know anything about this. It can transform from geographic to geocentric and UTM, and it can shift from NAD27 to NAD83 using interpolated shifts, but it can't incorporate the velocity grid the way TRX (see Mike T's answer) can.

Proj also doesn't do anything about the subtle differences between the various versions of ITRF and WGS84. There are no official transformation parameters between each iteration of ITRF and WGS84, but the original WGS84 was quite different, and there is a difference between each iteration. Proj, though, doesn't actually distinguish.

However, there is a transformation in the datum_shift.csv files (1515) which gives parameters for NAD83 to ITRF96(1997.0) and others, but these are not selected as defaults, and it wouldn't solve the tectonic/isostatic issues anyway.

ETA: I don't know whether Photoscan implements the velocity grid adjustment (the grids are freely available with the desktop version of TRX), and whether that accounts for the difference you're seeing.

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.