@@ -1140,23 +1140,28 @@ def __init__(self, *args):
11401140 and isinstance (arg [0 ], str )
11411141 and
11421142 # TODO: this should be extended to a slice.
1143- isinstance (arg [1 ], (int , np .integer ))
1143+ isinstance (arg [1 ], (int , np .integer , Projection ))
11441144 ), (
1145- "Each wire needs to be a tuple: (name, length). "
1145+ "Each wire needs to be a tuple: (name, length) or (name, Projection) . "
11461146 "You provided: {}" .format (arg )
11471147 )
11481148
1149- self ._nP = int (np .sum ([w [1 ] for w in args ]))
11501149 start = 0
11511150 maps = []
11521151 for arg in args :
1153- wire = Projection (self .nP , slice (start , start + arg [1 ]))
1152+
1153+ if isinstance (arg [1 ], (int , np .integer )):
1154+ wire = Projection (self .nP , slice (start , start + arg [1 ]))
1155+ start += arg [1 ]
1156+ else :
1157+ wire = arg [1 ]
1158+
11541159 setattr (self , arg [0 ], wire )
11551160 maps += [(arg [0 ], wire )]
1156- start += arg [1 ]
11571161 self .maps = maps
1158-
1159- self ._tuple = namedtuple ("Model" , [w [0 ] for w in args ])
1162+ self ._nP = maps [0 ][1 ].nP
1163+ self ._tuple = namedtuple ("Model" , [name for name , _ in args ])
1164+ self ._projection = sp .vstack ([wire .P for _ , wire in self .maps ])
11601165
11611166 def __mul__ (self , val ):
11621167 assert isinstance (val , np .ndarray )
@@ -1176,6 +1181,22 @@ def nP(self):
11761181 """
11771182 return self ._nP
11781183
1184+ def deriv (self , m ):
1185+ """
1186+ Derivative of the mapping with respect to the input parameters
1187+
1188+ Parameters
1189+ ----------
1190+ m : (n_param, ) numpy.ndarray
1191+ The model for which the gradient is evaluated.
1192+
1193+ Returns
1194+ -------
1195+ (n_param, ) numpy.ndarray
1196+ The Gradient of the mapping function evaluated for the model provided.
1197+ """
1198+ return self ._projection
1199+
11791200
11801201class TileMap (IdentityMap ):
11811202 """
0 commit comments