Example #1
0
def ITYPE_0(MTDatas, info, reactionSuite, singleMTOnly, MTs2Skip,
            parseCrossSectionOnly, doCovariances, verbose):

    warningList = []

    info.totalOrPromptFissionNeutrons = {}
    info.totalMF6_12_13Gammas = {}
    if (452 in MTDatas):
        info.totalOrPromptFissionNeutrons['total'] = getTotalOrPromptFission(
            info, MTDatas[452][1], 'total', warningList)
        #MTDatas.pop( 452 ) # don't remove these yet, still need the covariance info
    if (455 in MTDatas):
        info.delayedFissionDecayChannel = getDelayedFission(
            info, MTDatas[455], warningList)
        #MTDatas.pop( 455 )
    if (456 in MTDatas):
        info.totalOrPromptFissionNeutrons[
            tokensModule.promptToken] = getTotalOrPromptFission(
                info, MTDatas[456][1], tokensModule.promptToken, warningList)
        #MTDatas.pop( 456 )
    if (458 in MTDatas):
        info.fissionEnergies = getFissionEnergies(info, MTDatas[458],
                                                  warningList)
        #MTDatas.pop( 458 )
    if (454 in MTDatas):
        info.independentFissionYields = readMF8_454_459(
            info, 454, MTDatas[454], warningList)
    if (459 in MTDatas):
        info.cumulativeFissionYields = readMF8_454_459(info, 459, MTDatas[459],
                                                       warningList)
    sys.stdout.flush()
    for warning in warningList:
        info.logs.write("       WARNING: %s\n" % warning, stderrWriting=True)

    MTList = endfFileToGNDMiscModule.niceSortOfMTs(MTDatas.keys(),
                                                   verbose=False,
                                                   logFile=info.logs)

    haveTotalFission = (18 in MTList)
    fissionMTs = [mt for mt in MTList if mt in (19, 20, 21, 38)]

    summedReactions = {}
    summedReactionsInfo = {
        4: range(50, 92),
        103: range(600, 650),
        104: range(650, 700),
        105: range(700, 750),
        106: range(750, 800),
        107: range(800, 850)
    }
    for summedMT, partialReactions in summedReactionsInfo.items():
        if (summedMT not in MTList): continue
        for MT in MTList:
            if (MT in partialReactions):
                summedReactions[summedMT] = None
                break

    for summedMT in (1, 3):
        if (summedMT in MTList): summedReactions[summedMT] = None

    MT5Reaction = None
    reactions = []
    fissionComponents = []
    productions = []
    nonElastic = []
    delayInsertingSummedReaction = []

    for MT in MTList:
        if (MT in MTs2Skip): continue
        if ((singleMTOnly is not None) and (MT != singleMTOnly)): continue

        warningList = []
        MTData = MTDatas[MT]

        # Sometimes excited states are identified in MF8. Read this before reading distributions to make sure info is present.
        LMF, radioactiveDatas = readMF8(info, MT, MTData, warningList)

        doParseReaction = 3 in MTData
        if (not (doParseReaction)):
            if (MT == 3): doParseReaction = (12 in MTData) or (13 in MTData)
        if (doParseReaction
            ):  # normal reaction, with cross section and distributions
            try:
                crossSection, outputChannel, MFKeys = parseReaction(
                    info,
                    info.target,
                    info.projectileZA,
                    info.targetZA,
                    MT,
                    MTData,
                    warningList,
                    parseCrossSectionOnly=parseCrossSectionOnly)
            except KeyboardInterrupt:
                raise
            except:
                import traceback
                info.logs.write(traceback.format_exc(), stderrWriting=True)
                info.doRaise.append(traceback.format_exc())
                info.logs.write('\n')
                sys.stdout.flush()
                continue

            info.logs.write('\n')
            sys.stdout.flush()
            if (len(MFKeys)):
                warningList.append(
                    'For reaction MT = %d, the following MFs were not converted: %s\n'
                    % (MT, MFKeys))
            if (outputChannel is None): break

            if (MT in summedReactions):
                summedReactions[MT] = [crossSection, outputChannel]
            else:
                if (MT != 2): nonElastic.append(MT)
                reaction = reactionModule.reaction(outputChannel,
                                                   "%s" % 0,
                                                   ENDF_MT=MT,
                                                   date=info.Date)
                reaction.crossSection.add(crossSection)
                if (MT == 5):
                    MT5Reaction = reaction
                elif MT in fissionMTs and haveTotalFission:  # this is 1st, 2nd, etc fission but total is also present
                    fissionComponents.append(reaction)
                else:
                    if (MT in summedReactionsInfo):
                        delayInsertingSummedReaction.append(reaction)
                    else:
                        reactions.append([MT, reaction])
        else:
            MFList = []
            for MF in [4, 5, 6, 12, 13, 14, 15]:
                if (MF in MTData): MFList.append('%d' % MF)
            if (MFList != ''):
                warningList.append(
                    'MT = %d has MF = %s data and no MF 3 data' %
                    (MT, ', '.join(MFList)))

        for radioactiveData in radioactiveDatas:  # Get radioactive production data (if any) from MF 8-10. Cross section form depends on value of LMF.
            if (LMF in [3, 6, 9]):  # Cross section is reference to MF3.
                productionCrossSection = crossSectionModule.reference(
                    link=reaction.crossSection, label=info.style)
            elif (
                    LMF == 10
            ):  # MF10 data is cross section. Product's multipliticy is 1.
                productionCrossSection = radioactiveData[2]
            else:
                raise Exception(
                    "Unknown LMF=%d encountered in MF=8 for MT=%d" % (LMF, MT))

            Q = outputChannel.Q[info.style]
            if (LMF in [9, 10]):
                Q = toGNDMisc.returnConstantQ(info.style, radioactiveData[4])

            if (
                    LMF == 6
            ):  # Product multiplicity is in MF6, so production channel multiplicity needs to refer to it:
                MF6prod = outputChannel.getProductsWithName(
                    radioactiveData[1].name)

                if (len(MF6prod) !=
                        1):  # CMM: I'm not sure if we need this test anymore
                    warningList.append(
                        'Unique MT%d radioactive product %s not found in product list!'
                        % (MT, radioactiveData[1].name))
                    info.doRaise.append(warningList[-1])
                    continue

                radioactiveData[1].multiplicity.add(
                    multiplicityModule.reference(label=info.style,
                                                 link=MF6prod[0].multiplicity))
                radioactiveData[1].multiplicity.remove(
                    'unknown'
                )  # 'unknown' was put in as a place-holder by readMF8

            productionOutputChannel = channelsModule.productionChannel()
            productionOutputChannel.Q.add(Q)
            productionOutputChannel.products.add(
                productionOutputChannel.products.uniqueLabel(
                    radioactiveData[1]))

            production = productionModule.production(productionOutputChannel,
                                                     label=-1,
                                                     ENDF_MT=MT,
                                                     date=info.Date)
            production.crossSection.add(productionCrossSection)
            productions.append(production)

        for warning in warningList:
            info.logs.write("       WARNING: %s\n" % warning,
                            stderrWriting=True)

    iChannel = 0
    for MT, reaction in reactions:
        reaction.setLabel(str(iChannel))
        reactionSuite.reactions.add(reaction)
        iChannel += 1

    for reaction in delayInsertingSummedReaction:
        reaction.setLabel('%s' % iChannel)
        reactionSuite.reactions.add(reaction)
        iChannel += 1

    if (MT5Reaction is not None):
        MT5Reaction.setLabel("%s" % iChannel)
        reactionSuite.reactions.add(MT5Reaction)
        iChannel += 1

# BRB, The channelIDs should be in a common area?????
    channelIDs = {
        1: 'total',
        3: 'nonelastic',
        4: '(z,n)',
        103: '(z,p)',
        104: '(z,d)',
        105: '(z,t)',
        106: '(z,He3)',
        107: '(z,alpha)'
    }
    if (3 in summedReactions): summedReactionsInfo[3] = nonElastic
    if ((1 in summedReactions) and (2 in MTList)):
        summedReactionsInfo[1] = [2] + nonElastic
    summedReactionMTs = endfFileToGNDMiscModule.niceSortOfMTs(
        summedReactions.keys(), verbose=False, logFile=info.logs)
    for MT in (4, 3, 1):
        if (MT in summedReactionMTs):
            summedReactionMTs.remove(MT)
            summedReactionMTs.insert(0, MT)
    for i1, MT in enumerate(summedReactionMTs):
        if (summedReactions[MT] is None): continue
        crossSection, outputChannel = summedReactions[MT]
        if ((MT == 3) and (crossSection is None)):
            crossSection = deriveMT3MF3FromMT1_2(info, reactionSuite)
        summands = [
            sumsModule.add(link=r.crossSection)
            for r in reactionSuite.reactions
            if r.ENDF_MT in summedReactionsInfo[MT]
        ]
        summedCrossSection = sumsModule.crossSectionSum(
            name=channelIDs[MT],
            label=str(i1),
            ENDF_MT=MT,
            summands=sumsModule.listOfSummands(summandList=summands),
            date=info.Date)
        summedCrossSection.Q.add(outputChannel.Q[info.style])
        summedCrossSection.crossSection.add(crossSection)
        reactionSuite.sums.add(summedCrossSection)

        gammas = []
        for product in outputChannel:
            if (isinstance(product.particle, xParticleModule.photon)):
                gammas.append(product)
            else:
                if (product.outputChannel is not None):
                    for product2 in product.outputChannel:
                        if (isinstance(product2.particle,
                                       xParticleModule.photon)):
                            gammas.append(product2)
        if (len(gammas) > 0):
            productChannel = channelsModule.NBodyOutputChannel()
            for QForm in outputChannel.Q:
                productChannel.Q.add(QForm)
            for gamma in gammas:
                productChannel.products.add(
                    productChannel.products.uniqueLabel(gamma))
            productionReaction = productionModule.production(productChannel,
                                                             str(iChannel),
                                                             MT,
                                                             date=info.Date)
            crossSectionLink = crossSectionModule.reference(
                link=summedCrossSection.crossSection, label=info.style)
            productionReaction.crossSection.add(crossSectionLink)
            reactionSuite.reactions.add(productionReaction)
            iChannel += 1

    for i1, reaction in enumerate(
            fissionComponents
    ):  # 1st-chance, 2nd-chance, etc. Convert them to fissionComponent instances:
        fissionComponent = fissionComponentModule.fissionComponent(
            reaction.outputChannel,
            str(i1),
            reaction.ENDF_MT,
            date=reaction.date)
        for crossSection in reaction.crossSection:
            fissionComponent.crossSection.add(crossSection)
        reactionSuite.fissionComponents.add(fissionComponent)

    for i1, production in enumerate(productions):
        production.setLabel("%s" % i1)
        reactionSuite.productions.add(production)

    warningList = []
    try:  # Parse resonance section.
        mf2 = None
        if (151 in MTDatas and not parseCrossSectionOnly):
            mf2 = MTDatas.get(151).get(2)  # Resonance data available.
        if (mf2):
            info.logs.write('    Reading resonances (MF=2 MT=151)\n')
            resonances, resonanceMTs = readMF2(info, mf2, warningList)
            resonances.reconstructCrossSection = (
                info.LRP == 1)  # LRP was read in from first line of ENDF file
            if resonances.unresolved and not resonances.resolved:
                if resonances.unresolved.tabulatedWidths.forSelfShieldingOnly:
                    resonances.reconstructCrossSection = False
            reactionSuite.addResonances(resonances)

            # add spins appearing in resonance region to the particle list
            for particle, spinParity in info.particleSpins.items():
                if particle == 'target': particle = reactionSuite.target
                else: particle = reactionSuite.getParticle(particle)
                if isinstance(particle, xParticleModule.isotope
                              ) and particle.name not in ('gamma', 'n', 'H1'):
                    # spin should be associated with ground state level:
                    particle.addLevel(
                        xParticleModule.nuclearLevel(
                            name=particle.name + '_e0',
                            energy=PQUModule.PQU('0 eV'),
                            label=0))
                    particle = particle.levels[0]
                particle.attributes['spin'] = spinParity[0]
                if spinParity[1]: particle.attributes['parity'] = spinParity[1]

            if resonances.reconstructCrossSection:
                # modify cross sections for relevant channels to indicate resonance contribution is needed:
                resonanceLink = crossSectionModule.resonanceLink(
                    link=resonances)

                for MT in resonanceMTs:
                    MTChannels = [
                        r1 for r1 in reactionSuite.reactions
                        if (r1.getENDL_CS_ENDF_MT()['MT'] == MT)
                        and isinstance(r1, reactionModule.reaction)
                    ]
                    MTChannels += [
                        r1 for r1 in reactionSuite.sums if (r1.ENDF_MT == MT)
                    ]
                    MTChannels += [
                        r1 for r1 in reactionSuite.fissionComponents
                        if (r1.getENDL_CS_ENDF_MT()['MT'] == MT)
                    ]
                    if (len(MTChannels) == 0):
                        if (MT in (3, 18, 19)):
                            continue
                        else:
                            warningList.append(
                                'Unable to find channel corresponding to resonance data for MT%d'
                                % MT)
                    elif (len(MTChannels) == 1):
                        crossSectionComponent = MTChannels[0].crossSection
                        backgroundForm = crossSectionComponent[info.style]
                        crossSectionComponent.remove(backgroundForm.label)
                        crossSectionComponent.add(
                            crossSectionModule.resonancesWithBackground(
                                info.style, backgroundForm, resonanceLink))
                    else:
                        raise 'hell - FIXME'  # This may not be correct.
                        crossSectionComponent = MTChannels[0].crossSection
                        backgroundComponent = crossSectionComponent[
                            info.style].crossSection
                        backgroundForm = backgroundComponent[info.style]
                        backgroundComponent.remove(backgroundForm.label)
                        referredXSecForm = crossSectionModule.resonancesWithBackground(
                            info.style, backgroundForm, resonanceLink)
                        backgroundComponent.add(referredXSecForm)
    except BadResonances as e:
        warningList.append(
            '       ERROR: unable to parse resonances! Error message: %s' % e)
        info.doRaise.append(warningList[-1])

    if (doCovariances):
        covarianceMFs = sorted(
            set([mf for mt in MTDatas.values() for mf in mt.keys()
                 if mf > 30]))
        if covarianceMFs:
            info.logs.write('    Reading covariances (MFs %s)\n' %
                            ','.join(map(str, covarianceMFs)))
        try:
            """ parse covariances. This also requires setting up links from data to covariances, so we
            must ensure the links are synchronized """

            MTdict = {}
            for reaction in reactionSuite:
                MT = reaction.ENDF_MT
                if MT in MTdict:
                    MTdict[MT].append(reaction)
                else:
                    MTdict[MT] = [reaction]
            covarianceSuite, linkData = parseCovariances(
                info,
                MTDatas,
                MTdict,
                singleMTOnly=singleMTOnly,
                resonances=getattr(reactionSuite, 'resonances', None))
            if (len(covarianceSuite) > 0):
                covarianceSuite.target = str(info.target)
                covarianceSuite.projectile = str(info.projectile)
                covarianceSuite.styles.add(info.evaluatedStyle)
                #covarianceSuite.removeExtraZeros() # disable for easier comparison to ENDF
            else:
                covarianceSuite = None
        except Exception as e:
            warningList.append(
                "Couldn't parse covariances! Error message: %s" % e)
            info.doRaise.append(warningList[-1])
            covarianceSuite = None
            raise
    else:
        covarianceSuite = None

    for ZA in info.ZA_AWRMasses:
        mostCount = 0
        for AWR in info.ZA_AWRMasses[ZA]:
            if (info.ZA_AWRMasses[ZA][AWR] > mostCount):
                mostCount = info.ZA_AWRMasses[ZA][AWR]
                mostAWR = AWR
        info.ZA_AWRMasses[ZA] = mostAWR * info.masses.getMassFromZA(1)

    if (info.level >
            0):  # AWR is for isomer mass. Adjust info.ZAMasses to GS mass:
        info.ZA_AWRMasses[info.targetZA] -= PQUModule.PQU(
            PQUModule.pqu_float.surmiseSignificantDigits(info.level),
            'eV/c**2').getValueAs('amu')

    for particle in reactionSuite.particles:  # Fix up any particle whose mass is not defined (i.e., is None).
        if (particle.name == 'gamma'): continue
        ZA = nuclear.getZ_A_suffix_andZAFromName(particle.name)[3]
        mass = particle.getMass('amu')
        if (ZA in info.ZA_AWRMasses):
            mass = info.ZA_AWRMasses[ZA]
        elif ((mass is None) or (ZA in info.ZAMasses)):
            if (info.ZAMasses[ZA] is None):
                mass = info.masses.getMassFromZA(ZA)
            else:
                mass = abs(info.ZAMasses[ZA])
        particle.setMass(
            PQUModule.PQU(PQUModule.pqu_float.surmiseSignificantDigits(mass),
                          'amu'))
        # also add ground state level if there are discrete excited levels.
        levels = particle.levels.keys()
        if ('s' in levels): levels.remove('s')
        if ('c' in levels): levels.remove('c')
        if ((len(levels) > 0) and (0 not in levels)):
            # BRB, Caleb, we should not hardwire the '_e0' here, need to implements naming in the xParticle.py module.
            particle.addLevel(
                xParticleModule.nuclearLevel(
                    name=particle.name + '_e0',
                    energy=PQUModule.PQU(
                        PQUModule.pqu_float.surmiseSignificantDigits(0), 'eV'),
                    label=0))

    MF12BaseMTsAndRange = [[50, 92], [600, 650], [650, 700], [700, 750],
                           [750, 800], [800, 850]]

    if (singleMTOnly is None):
        branchingData = None
        #if( len( info.MF12_LO2 ) > 0 ) : reactionSuite.gammaBranching = {}
        for MTLO2, MF12_LO2 in sorted(info.MF12_LO2.items(
        )):  # The logic below assumes MTs are in ascending order per base MT.
            branchingBaseMT = None
            for MTBase, MTEnd in MF12BaseMTsAndRange:  # Determine base MT for this MTLO2
                if (MTBase < MTLO2 < MTEnd):
                    branchingBaseMT = MTBase
                    break
            if (branchingBaseMT is not None):
                residualZA = endf_endl.ENDF_MTZAEquation(
                    info.projectileZA, info.targetZA, branchingBaseMT)[0][-1]
                residual = toGNDMisc.getTypeNameENDF(info, residualZA, None)
                residualName = residual.name
                level = MTLO2 - branchingBaseMT
                levelName, levelEnergy = '_e%d' % level, MF12_LO2[0]['ES']
                fullName = residualName + levelName
                levelEnergy_eV = PQUModule.PQU(
                    PQUModule.pqu_float.surmiseSignificantDigits(levelEnergy),
                    'eV')
                # compare this value to level energy from the particle list (from MF3 Q-value).
                particleLevelEnergy_eV = reactionSuite.getParticle(
                    fullName).energy
                if (levelEnergy_eV.value != particleLevelEnergy_eV.value):
                    if (particleLevelEnergy_eV.value < 1e-12):
                        warningList.append(
                            "MF12 parent level energy (%s) set to zero?" %
                            particleLevelEnergy_eV)
                        info.doRaise.append(warningList[-1])
                    elif (abs(levelEnergy_eV - particleLevelEnergy_eV) /
                          particleLevelEnergy_eV < 1e-4):
                        MFLabel = '3'
                        # Value with most precision wins.
                        str1 = PQUModule.floatToShortestString(
                            levelEnergy_eV *
                            1e-20)  # 1e-20 to insure e-form is returned.
                        str2 = PQUModule.floatToShortestString(
                            particleLevelEnergy_eV *
                            1e-20)  # Want 1.23e-16 and not 12300 to differ
                        if (len(str1) > len(str2)
                            ):  # length from 1.2345e-16 and not 12345.
                            reactionSuite.getParticle(
                                fullName).energy = levelEnergy_eV
                            MFLabel = '12'
                        warningList.append( "MF12 level energy %s differs from MF3 value %s. Setting to MF%s value." % \
                                ( levelEnergy_eV, particleLevelEnergy_eV, MFLabel ) )
                    else:
                        warningList.append(
                            "MF12 parent level energy (%s) doesn't match known level"
                            % particleLevelEnergy_eV)
                        info.doRaise.append(warningList[-1])
                for MF12 in MF12_LO2:
                    try:
                        finalLevelEnergy = MF12['ESk']
                        if (finalLevelEnergy > 0.):
                            # find particle in the particleList with energy == finalLevelEnergy
                            finalParticles = [
                                lev for lev in reactionSuite.getParticle(
                                    residualName).levels.values() if
                                lev.energy.getValueAs('eV') == finalLevelEnergy
                            ]
                            if (len(finalParticles) == 1):
                                finalParticle = finalParticles[0]
                            else:  # no exact match, look for levels within .01% of the exact value.
                                idx = 0
                                while (True):
                                    idx += 1
                                    finalParticleName = residualName + '_e%i' % idx
                                    if (not reactionSuite.hasParticle(
                                            finalParticleName)):
                                        warningList.append( "MF12 final level energy (%s eV) doesn't match known level when decaying out of level %s " % \
                                                ( finalLevelEnergy, MTLO2 ) )
                                        info.doRaise.append(warningList[-1])
                                    thisLevelEnergy = reactionSuite.getParticle(
                                        finalParticleName).energy.getValueAs(
                                            'eV')
                                    if (abs(thisLevelEnergy - finalLevelEnergy)
                                            < 1e-4 * finalLevelEnergy):
                                        finalParticle = reactionSuite.getParticle(
                                            finalParticleName)
                                        break  # found it
                        else:
                            finalParticle = reactionSuite.getParticle(
                                residualName + '_e0')
                        gammaTransition = 1.
                        if (len(MF12['branching']) > 2):
                            gammaTransition = MF12['branching'][1]
                        gamma = xParticleModule.nuclearLevelGamma(
                            finalParticle, MF12['angularSubform'],
                            MF12['branching'][0], 1 - gammaTransition)
                        reactionSuite.getParticle(fullName).addGamma(gamma)
                    except Exception, err:
                        warningList.append(
                            'raise somewhere in "for MF12 in MF12_LO2" loop: MT%d, %s'
                            % (MT, str(err)))
                        info.doRaise.append(warningList[-1])
            else:
                raise Exception(
                    "Could not determine base MT for MF=12's MT=%s" % MTLO2)
Example #2
0
def ITYPE_0( MTDatas, info, reactionSuite, singleMTOnly, MTs2Skip, parseCrossSectionOnly, doCovariances, verbose, reconstructResonances=True ) :

    warningList = []

    info.totalOrPromptFissionNeutrons = {}
    info.totalMF6_12_13Gammas = {}
    if( 452 in MTDatas ) :
        info.totalOrPromptFissionNeutrons['total'] = getTotalOrPromptFission( info, MTDatas[452][1], 'total', warningList )
        #MTDatas.pop( 452 ) # don't remove these yet, still need the covariance info
    if( 455 in MTDatas ) :
        info.delayedFissionDecayChannel = getDelayedFission( info, MTDatas[455], warningList )
        #MTDatas.pop( 455 )
    if( 456 in MTDatas ) :
        info.totalOrPromptFissionNeutrons[tokensModule.promptToken] = getTotalOrPromptFission( info, MTDatas[456][1], tokensModule.promptToken, warningList )
        #MTDatas.pop( 456 )
    if( 458 in MTDatas ) :
        info.fissionEnergyReleaseData = MTDatas[458]
        #MTDatas.pop( 458 )
    if ( 454 in MTDatas ) : 
        info.independentFissionYields = readMF8_454_459( info, 454, MTDatas[454], warningList )
    if ( 459 in MTDatas ) : 
        info.cumulativeFissionYields = readMF8_454_459( info, 459, MTDatas[459], warningList )
    sys.stdout.flush( )
    for warning in warningList : info.logs.write( "       WARNING: %s\n" % warning, stderrWriting = True )

    MTList = endfFileToGNDMiscModule.niceSortOfMTs( MTDatas.keys( ), verbose = False, logFile = info.logs )

    haveTotalFission = (18 in MTList)
    fissionMTs = [mt for mt in MTList if mt in (19,20,21,38)]

    summedReactions = {}
    summedReactionsInfo = { 4 : range( 50, 92 ), 103 : range( 600, 650 ), 104 : range( 650, 700 ), 105 : range( 700, 750 ), 106 : range( 750, 800 ), 107 : range( 800, 850 ) }
    for summedMT, partialReactions in summedReactionsInfo.items( ) :
        if( summedMT not in MTList ) : continue
        for MT in MTList :
            if( MT in partialReactions ) :
                summedReactions[summedMT] = None
                break

    for summedMT in ( 1, 3 ) :
        if( summedMT in MTList ) : summedReactions[summedMT] = None

    MT5Reaction = None
    reactions = []
    fissionComponents = []
    productions = []
    nonElastic = []
    delayInsertingSummedReaction = []
    linksToCheck = []   # links that may need to be updated after reading resonances

    for MT in MTList :
        if( MT in MTs2Skip ) : continue
        if( ( singleMTOnly is not None ) and ( MT != singleMTOnly ) ) : continue

        warningList = []
        MTData = MTDatas[MT]

        # Sometimes excited states are identified in MF8. Read this before reading distributions to make sure info is present.
        LMF, radioactiveDatas = readMF8( info, MT, MTData, warningList )

        doParseReaction = 3 in MTData
        if( not( doParseReaction ) ) :
            if( MT == 3 ) : doParseReaction = ( 12 in MTData ) or ( 13 in MTData )
        if( doParseReaction ) : # normal reaction, with cross section and distributions
            try :
                crossSection, outputChannel, MFKeys = parseReaction( info, info.target, info.projectileZA,
                        info.targetZA, MT, MTData, warningList, parseCrossSectionOnly = parseCrossSectionOnly )
            except KeyboardInterrupt:
                raise
            except:
                import traceback
                info.logs.write( traceback.format_exc( ), stderrWriting = True )
                info.doRaise.append( traceback.format_exc( ) )
                info.logs.write( '\n' )
                sys.stdout.flush( )
                continue

            info.logs.write( '\n' )
            sys.stdout.flush( )
            if( len( MFKeys ) ) :
                warningList.append( 'For reaction MT = %d, the following MFs were not converted: %s\n' % ( MT, MFKeys ) )
            if( outputChannel is None ) : break

            if( MT in summedReactions ) :
                summedReactions[MT] = [ crossSection, outputChannel ]
            else :
                if( MT != 2 ) : nonElastic.append( MT )
                reaction = reactionModule.reaction( outputChannel, ENDF_MT = MT )
                if( hasattr( info, 'dSigma_form' ) ) :
                    reaction.dCrossSection_dOmega.add( info.dSigma_form )
                    del info.dSigma_form
                    crossSection = crossSectionModule.CoulombElasticReference( link = reaction.dCrossSection_dOmega.evaluated,
                            label = info.style, relative = True )
                reaction.crossSection.add( crossSection )
                if( MT == 5 ) :
                    MT5Reaction = reaction
                elif MT in fissionMTs and haveTotalFission: # this is 1st, 2nd, etc fission but total is also present

                    from fudge.gnd.channelData.fissionEnergyReleased import fissionEnergyReleased
                    if isinstance( reaction.outputChannel.Q.evaluated, fissionEnergyReleased ):
                        Qcomponent = reaction.outputChannel.Q
                        qval = toGNDMiscModule.returnConstantQ( info.style,
                            Qcomponent.evaluated.nonNeutrinoEnergy.data.coefficients[0],
                            crossSection )
                        Qcomponent.remove( info.style )
                        Qcomponent.add( qval ) # just put the approximate constant Q-value on 1st-chance, 2nd-chance etc.

                    fissionComponents.append( reaction )
                else :
                    if( MT in summedReactionsInfo ) :
                        delayInsertingSummedReaction.append( reaction )
                    else :
                        reactions.append( [ MT, reaction ] )
        else :
            MFList = []
            for MF in [ 4, 5, 6, 12, 13, 14, 15 ] :
                if( MF in MTData ) : MFList.append( '%d' % MF )
            if( MFList != [] ) : warningList.append( 'MT = %d has MF = %s data and no MF 3 data' % ( MT, ', '.join( MFList ) ) )

        for radioactiveData in radioactiveDatas : # Get radioactive production data (if any) from MF 8-10. Cross section form depends on value of LMF.
            if( LMF in [ 3, 6, 9 ] ) :  # Cross section is reference to MF3.
                productionCrossSection = crossSectionModule.reference( link = reaction.crossSection.evaluated, label = info.style )
                linksToCheck.append( productionCrossSection )
            elif( LMF == 10 ) :         # MF10 data is cross section. Product's multipliticy is 1.
                productionCrossSection = radioactiveData[4]
            else :
                raise Exception( "Unknown LMF=%d encountered in MF=8 for MT=%d" % ( LMF, MT ) )

            ZAP = radioactiveData[0]
            ELFS = radioactiveData[1]
            LFS = radioactiveData[2]

            Q = outputChannel.Q[info.style]
            if( LMF in [ 9, 10 ] ) :
                Q = toGNDMiscModule.returnConstantQ( info.style, radioactiveData[6], crossSection )

            if( LMF == 6 ) :      # Product multiplicity is in MF6, so production channel multiplicity needs to refer to it:
                residual = toGNDMiscModule.getTypeNameGamma( info, ZAP, level = ELFS, levelIndex = LFS )
                MF6prod = outputChannel.getProductsWithName( residual.id )

                if( len( MF6prod ) != 1 ) : # problem appears in JEFF-3.2 Y90 and Y91
                    warningList.append( 'Unique MT%d radioactive product %s not found in product list!' %
                                ( MT, residual.id ) )
                    info.doRaise.append( warningList[-1] )
                    continue

                multiplicity = multiplicityModule.reference( label = info.style, link = MF6prod[0].multiplicity )
            else :
                multiplicity = radioactiveData[3]

            try :
                residual = toGNDMiscModule.newGNDParticle( info, toGNDMiscModule.getTypeNameGamma( info, ZAP, level = ELFS, levelIndex = LFS ),
                        crossSection, multiplicity = multiplicity )
            except :
                info.logs.write( '\nMT = %s\n' % MT )
                raise

            productionOutputChannel = channelsModule.productionChannel( )
            productionOutputChannel.Q.add( Q )
            productionOutputChannel.products.add( productionOutputChannel.products.uniqueLabel( residual ) )
            productionOutputChannel.process = "%s%s" % (reactionSuite.target,
                        endf_endlModule.endfMTtoC_ProductLists[MT].reactionLabel.replace('z,', reactionSuite.projectile+',') )

            production = productionModule.production( productionOutputChannel, ENDF_MT = MT )
            production.crossSection.add( productionCrossSection )
            productions.append( production )

        for warning in warningList : info.logs.write( "       WARNING: %s\n" % warning, stderrWriting = True )

    for MT, reaction in reactions :
        reactionSuite.reactions.add( reaction )

    for reaction in delayInsertingSummedReaction :
        reactionSuite.reactions.add( reaction )

    if( MT5Reaction is not None ) :
        reactionSuite.reactions.add( MT5Reaction )

# BRB, The channelIDs should be in a common area?????
    channelIDs = { 1 : 'total', 3 : 'nonelastic', 4 : '(z,n)', 103 : '(z,p)', 104 : '(z,d)', 105 : '(z,t)', 106 : '(z,He3)', 107 :'(z,alpha)' }
    if( 3 in summedReactions ) : summedReactionsInfo[3] = nonElastic
    if( ( 1 in summedReactions ) and ( 2 in MTList ) ) : summedReactionsInfo[1] = [ 2 ] + nonElastic
    summedReactionMTs = endfFileToGNDMiscModule.niceSortOfMTs( summedReactions.keys( ), verbose = False, logFile = info.logs )
    for MT in ( 4, 3, 1 ) :
        if( MT in summedReactionMTs ) :
            summedReactionMTs.remove( MT )
            summedReactionMTs.insert( 0, MT )
    for i1, MT in enumerate( summedReactionMTs ) :
        if( summedReactions[MT] is None ) : continue
        crossSection, outputChannel = summedReactions[MT]
        if( ( MT == 3 ) and ( crossSection is None ) ) : 
            crossSection = deriveMT3MF3FromMT1_2( info, reactionSuite )
        summands = [ sumsModule.add( link = r.crossSection ) for r in reactionSuite.reactions if r.ENDF_MT in summedReactionsInfo[MT] ]
        summedCrossSection = sumsModule.crossSectionSum( label = channelIDs[MT], ENDF_MT = MT,
                summands = sumsModule.listOfSummands( summandList = summands ) )
        summedCrossSection.Q.add( outputChannel.Q[info.style] )
        summedCrossSection.crossSection.add( crossSection )
        reactionSuite.sums.crossSections.add( summedCrossSection )

        gammas = []
        for product in outputChannel :
            particle = reactionSuite.PoPs[product.id]
            if( isinstance( particle, gaugeBosonModule.particle ) ) :
                gammas.append( product )
            else :
                if( product.outputChannel is not None ) :
                    for product2 in product.outputChannel :
                        particle = reactionSuite.PoPs[product2.id]
                        if( isinstance( particle, gaugeBosonModule.particle ) ) : gammas.append( product2 )
        if( len( gammas ) > 0 ) :
            productChannel = channelsModule.NBodyOutputChannel( )
            for QForm in outputChannel.Q : productChannel.Q.add( QForm )
            for gamma in gammas : productChannel.products.add( productChannel.products.uniqueLabel( gamma ) )
            productionReaction = reactionModule.reaction( productChannel, ENDF_MT = MT, label = str( i1 ) )
            crossSectionLink = crossSectionModule.reference( link = summedCrossSection.crossSection.evaluated, label = info.style )
            linksToCheck.append( crossSectionLink )
            productionReaction.crossSection.add( crossSectionLink )
            reactionSuite.orphanProducts.add( productionReaction )

    for i1, reaction in enumerate( fissionComponents ) :  # 1st-chance, 2nd-chance, etc. Convert them to fissionComponent instances:
        fissionComponent = fissionComponentModule.fissionComponent( reaction.outputChannel, reaction.ENDF_MT )
        for crossSection in reaction.crossSection : fissionComponent.crossSection.add( crossSection )
        reactionSuite.fissionComponents.add( fissionComponent )

    for i1, production in enumerate( productions ) :
        reactionSuite.productions.add( production )

    if hasattr( info, 'totalDelayedMultiplicity' ):
        prompt, delayed = [], []
        for neutron in reactionSuite.getReaction('fission').outputChannel.getProductsWithName( IDsPoPsModule.neutron ):
            link_ = sumsModule.add( link = neutron.multiplicity )
            if neutron.getAttribute('emissionMode') == tokensModule.delayedToken:
                delayed.append( link_ )
            else:
                prompt.append( link_ )

        delayedNubar = sumsModule.multiplicitySum( label = "delayed fission neutron multiplicity",
                ENDF_MT = 455, summands = sumsModule.listOfSummands(delayed) )
        delayedNubar.multiplicity.add( info.totalDelayedMultiplicity )
        reactionSuite.sums.multiplicities.add( delayedNubar )

        total = prompt + [sumsModule.add( link = delayedNubar.multiplicity )]
        totalNubar = sumsModule.multiplicitySum( label = "total fission neutron multiplicity",
                ENDF_MT = 452, summands = sumsModule.listOfSummands(total) )
        totalNubar.multiplicity.add( info.totalOrPromptFissionNeutrons['total'] )
        reactionSuite.sums.multiplicities.add( totalNubar )

    warningList = []
    try :               # Parse resonance section.
        mf2 = None
        if( 151 in MTDatas and not parseCrossSectionOnly ) :
            mf2 = MTDatas.get( 151 ).get( 2 )    # Resonance data available.
        if( mf2 ) :
            info.logs.write( '    Reading resonances (MF=2 MT=151)\n' )
            resonances, resonanceMTs = readMF2( info, mf2, warningList )
            kReconstruct = ( info.LRP == 1 )   # LRP was read in from first line of ENDF file
            if resonances.resolved: resonances.resolved.reconstructCrossSection = kReconstruct
            reactionSuite.addResonances( resonances )

            if resonances.reconstructCrossSection:
                # modify cross sections for relevant channels to indicate resonance contribution is needed:
                resonanceLink = crossSectionModule.resonanceLink( link = resonances )

                for MT in resonanceMTs :
                    MTChannels  = [ r1 for r1 in reactionSuite.reactions         if( r1.getENDL_CS_ENDF_MT()['MT'] == MT )
                                    and isinstance(r1, reactionModule.reaction) ]
                    MTChannels += [ r1 for r1 in reactionSuite.sums.crossSections   if( r1.ENDF_MT == MT ) ]
                    MTChannels += [ r1 for r1 in reactionSuite.fissionComponents if( r1.getENDL_CS_ENDF_MT()['MT'] == MT ) ]
                    if( len( MTChannels ) == 0 ) :
                        if( MT in ( 3, 18, 19 ) ) :
                            continue
                        else :
                            warningList.append( 'Unable to find channel corresponding to resonance data for MT%d' % MT )
                    elif( len( MTChannels ) == 1 ) :
                        crossSectionComponent = MTChannels[0].crossSection
                        backgroundForm = crossSectionComponent[info.style]
                        backgroundForm.label = None
                        crossSectionComponent.remove( backgroundForm.label )
                        crossSectionComponent.add( crossSectionModule.resonancesWithBackground( info.style, backgroundForm, resonanceLink ) )
                        for link in linksToCheck:
                            if link.link is backgroundForm:
                                link.link = crossSectionComponent[ info.style ]
                    else :
                        raise 'hell - FIXME'                # This may not be correct.
                        crossSectionComponent = MTChannels[0].crossSection
                        backgroundComponent = crossSectionComponent[info.style].crossSection
                        backgroundForm = backgroundComponent[info.style]
                        backgroundComponent.remove( backgroundForm.label )
                        referredXSecForm = crossSectionModule.resonancesWithBackground( info.style, backgroundForm, resonanceLink )
                        backgroundComponent.add( referredXSecForm )

    except BadResonances as e:
        warningList.append( '       ERROR: unable to parse resonances! Error message: %s' % e )
        info.doRaise.append( warningList[-1] )

    if( doCovariances ) :
        covarianceMFs = sorted( set( [mf for mt in MTDatas.values() for mf in mt.keys() if mf>30] ) )
        if covarianceMFs:
            info.logs.write( '    Reading covariances (MFs %s)\n' % ','.join(map(str,covarianceMFs) ) )
        try:
            """ parse covariances. This also requires setting up links from data to covariances, so we
            must ensure the links are synchronized """

            MTdict = {}
            for reaction in ( list( reactionSuite.reactions ) + list( reactionSuite.sums.crossSections ) + list( reactionSuite.productions ) 
                    + list( reactionSuite.fissionComponents ) ) :
                MT = reaction.ENDF_MT
                if MT in MTdict:
                    MTdict[MT].append( reaction )
                else:
                    MTdict[MT] = [reaction]
            covarianceSuite, linkData = parseCovariances( info, MTDatas, MTdict, singleMTOnly = singleMTOnly,
                    resonances = getattr( reactionSuite, 'resonances', None ) )
            if( len( covarianceSuite ) > 0 ) :
                covarianceSuite.target = str(info.target)
                covarianceSuite.projectile = str(info.projectile)
                covarianceSuite.styles.add( info.evaluatedStyle )
                #covarianceSuite.removeExtraZeros() # disable for easier comparison to ENDF
            else :
                covarianceSuite = None
        except Exception as e:
            warningList.append( "Couldn't parse covariances! Error message: %s" % e )
            info.doRaise.append( warningList[-1] )
            covarianceSuite = None
            raise
    else :
        covarianceSuite = None

    info.massTracker.useMostCommonAMUmasses()

    if( info.level > 0 ) : # AWR is for isomer mass. Adjust info.ZAMasses to GS mass:
        groundStateMass = info.massTracker.getMassAMU( info.targetZA ) - PQUModule.PQU(
            PQUModule.pqu_float.surmiseSignificantDigits( info.level ),'eV/c**2').getValueAs('amu')
        info.massTracker.addMassAMU( info.targetZA, groundStateMass )  # overwrite excited state mass

    for ZA in info.massTracker.amuMasses :
        if( ZA in [ 1 ] ) : continue
        mass = info.massTracker.amuMasses[ZA]
        elementSymbol = chemicalElementModule.symbolFromZ[ZA/1000]
        A = str( ZA % 1000 )
        name = isotopeModule.isotopeIDFromElementIDAndA( elementSymbol, A )
        name = nucleusModule.levelNameFromIsotopeNameAndIndex( name, '0' )
        mass = massModule.double( info.PoPsLabel, mass, quantityModule.stringToPhysicalUnit( 'amu' ) )
        if( name not in reactionSuite.PoPs ) : toGNDMiscModule.getPoPsParticle( info, ZA, levelIndex = 0 )
        particle = reactionSuite.PoPs[name]
        particle.mass.add( mass )

    MF12BaseMTsAndRange = [ [ 50, 92 ], [ 600, 650 ], [ 650, 700 ], [ 700, 750 ], [ 750, 800 ], [ 800, 850 ] ]

    if( singleMTOnly is None ) :
        branchingData = None
        #if( len( info.MF12_LO2 ) > 0 ) : reactionSuite.gammaBranching = {}
        for MTLO2, MF12_LO2 in sorted(info.MF12_LO2.items()) :  # The logic below assumes MTs are in ascending order per base MT.
            branchingBaseMT = None
            for MTBase, MTEnd in MF12BaseMTsAndRange :             # Determine base MT for this MTLO2
                if( MTBase < MTLO2 < MTEnd ) :
                    branchingBaseMT = MTBase
                    break
            if( branchingBaseMT is not None ) :
                residualZA = endf_endlModule.ENDF_MTZAEquation( info.projectileZA, info.targetZA, branchingBaseMT )[0][-1]
                residual = toGNDMiscModule.getTypeNameENDF( info, residualZA, None )
                residualName = residual.id
                if( isinstance( residual, nuclearLevelModule.particle ) ) : residualName = residual.getAncestor( ).id
                level = MTLO2 - branchingBaseMT
                levelName, levelEnergy = '_e%d' % level, MF12_LO2[0]['ES']
                fullName = residualName + levelName
                    # compare this value to level energy from the particle list (from MF3 Q-value).
                particleLevelEnergy_eV = reactionSuite.PoPs[fullName].energy[0].value
                if( levelEnergy != particleLevelEnergy_eV ) :
                    if( particleLevelEnergy_eV < 1e-12 ) :
                        warningList.append( "MF12 parent level energy (%s) set to zero?" % particleLevelEnergy_eV )
                        info.doRaise.append( warningList[-1] )
                    elif( abs( levelEnergy - particleLevelEnergy_eV ) < 1e-4 * particleLevelEnergy_eV ) :
                        MFLabel = '3'
                                                                                            # Value with most precision wins.
                        str1 = PQUModule.floatToShortestString( levelEnergy * 1e-20 )          # 1e-20 to insure e-form is returned.
                        str2 = PQUModule.floatToShortestString( particleLevelEnergy_eV * 1e-20 )  # Want 1.23e-16 and not 12300 to differ
                        if( len( str1 ) > len( str2 ) ) :                                   # length from 1.2345e-16 and not 12345.
                            reactionSuite.PoPs[fullName].energy[0].value = levelEnergy
                            MFLabel = '12'
                        warningList.append( "MT%d MF12 level energy %s differs from MF3 value %s. Setting to MF%s value." %
                                ( MTLO2, levelEnergy, particleLevelEnergy_eV, MFLabel ) )
                    else :
                        warningList.append( "MT%d MF12 parent level energy (%s) doesn't match known level" % ( MTLO2, particleLevelEnergy_eV ) )
                        info.doRaise.append( warningList[-1] )
                for i1, MF12 in enumerate( MF12_LO2 ) :
                    try :
                        finalLevelEnergy = MF12['ESk']
                        if( finalLevelEnergy > 0. ) :   # Find particle in the particleList with energy = finalLevelEnergy
                            finalParticles = [ lev for lev in reactionSuite.getParticle( residualName )
                                    if lev.energy.float('eV') == finalLevelEnergy ]
                            if( len( finalParticles ) == 1 ) :
                                finalParticle = finalParticles[0]
                            else :                      # No exact match, look for levels within .01% of the exact value.
                                idx = 0
                                while( True ) :
                                    idx += 1
                                    finalParticleName = residualName+'_e%i'%idx
                                    if( not reactionSuite.hasParticle( finalParticleName ) ) :
                                        warningList.append( "MF12 final level energy (%s eV) doesn't match known level when decaying out of level %s " % \
                                                ( finalLevelEnergy, MTLO2 ) )
                                        info.doRaise.append( warningList[-1] )
                                    thisLevelEnergy = reactionSuite.getParticle(finalParticleName).energy.pqu().getValueAs('eV')
                                    if( abs( thisLevelEnergy - finalLevelEnergy ) < 1e-4 * finalLevelEnergy ) :
                                        finalParticle = reactionSuite.getParticle(finalParticleName)
                                        break   # found it
                        else :
                            finalParticle = reactionSuite.getParticle(residualName+'_e0')
                        gammaTransition = 1.
                        if( len( MF12['branching'] ) > 2 ) : gammaTransition = MF12['branching'][1]

                        if( gammaTransition != 1 ) : raise Exception( 'Fix me' )
                        probability = probabilityModule.double( info.PoPsLabel, MF12['branching'][0] )

                        decayMode = decayDataModule.decayMode( str( i1 ), IDsPoPsModule.photon )
                        decayMode.probability.add( probability )
                        _decay = decayDataModule.decay( str( i1 ), decayDataModule.decayModesParticle)
                        _decay.products.add( productModule.product( IDsPoPsModule.photon, IDsPoPsModule.photon ) )
                        _decay.products.add( productModule.product( finalParticle.id, finalParticle.id ) )
                        decayMode.decayPath.add( _decay )
                        reactionSuite.PoPs[fullName].nucleus.decayData.decayModes.add( decayMode )
                    except Exception, err :
                        raise
                        warningList.append( 'raise somewhere in "for MF12 in MF12_LO2" loop: MT%d, %s' % ( MT, str( err ) ) )
                        info.doRaise.append( warningList[-1] )
            else :
                raise Exception( "Could not determine base MT for MF=12's MT=%s" % MTLO2 )