How to link deepCoadd objects to forced_src ones?

deepCoadd objects belong to catalogs identified by (patch, tract, filter), while forced_src objects belong to catalogs identified by (visit, ccd, filter, tract). If I understand well, objects which are common to deepCoadd and forced_src catalogs share the same “id” (in fact “objectId” in forced_src and “id” in deepCoadd).

The question is how can we identify the forced_src catalog that contains a given object which is present in a deepCoadd catalog ?

If this association is not possible at the object level, is there a function which returns the list of forced_src dataId matching a given (patch, tract, filter) ?

I haven’t run forcedPhotCcd.py for a while, but it should be using the reference catalog generated by the multiband processing scheme, in which case the objectId (or maybe just id; I forget) in forced_src should correspond to the id in the deepCoadd_ref.

Yes I checked that it is the case. But the problem is the following:
If I have a deepCoadd_ref object with a given objectId, how can I find the corresponding dataId to be passed to the butler in order to open the right forced_src catalog. Is this information coded in the objectId ?

Ah, sorry, I didn’t grok the question.

The visit and ccd are stored in the deepCoadd. Try something like this:

coaddId = dict(tract=12345, patch='6,7', filter="i")
exp = butler.get("deepCoadd", coaddId, immediate=True)
ccdInputs = exp.getInfo().getCoaddInfo().ccds
visitKey = ccdInputs.schema.find("visit").key
ccdKey = ccdInputs.schema.find("ccd").key
for ccdRecord in ccdInputs:
    dataId = dict(visit=ccdRecord.get(visitKey), ccd=ccdRecord.get(ccdKey))
    # Work around problem with adding 'tract' to key
    dataRefList = list(butler.subset("raw", dataId))
    assert(len(dataRefList) == 0)
    dataRef = dataRefList.pop()
    forced = dataRef.get("forced_src", tract=coaddId['tract'], immediate=True)

I took the bones of this from lsst.pipe.tasks.propagateVisitFlags.

The problem with adding tract to the dataId is mentioned here.

Thanks a lot @price
Here is the piece of code I just tested (there are a few things I had to adjust, for instance butler.subset does not seem to accep a dict as argument):

coaddId = dict(tract=0, patch='2,4', filter="u")
coadd = butler.get("deepCoadd", coaddId, immediate=True)
ccdInputs = coadd.getInfo().getCoaddInputs().ccds

visitKey = ccdInputs.schema.find("visit").key
ccdKey = ccdInputs.schema.find("ccd").key

for ccdRecord in ccdInputs:
    v = ccdRecord.get(visitKey)
    c = ccdRecord.get(ccdKey)
    print v, c
    dataRefList = list(butler.subset("raw", visit=int(v), ccd=int(c)))
    assert(len(dataRefList) != 0)
    dataRef = dataRefList.pop()
    forced = dataRef.get("forced_src", tract=coaddId['tract'], immediate=True)