def makegroup(snap, output):
    g = snap.readgroup()
    outarray = dirarray(os.path.join(output, 'group'), 
        dtype=[('x', 'f4'), 
            ('y', 'f4'), 
            ('mass', 'f4'), 
            ('pos', ('f4', 3)), 
            ('massbytype', ('f4', 6)), 
            ('lenbytype', ('u4',6)), 
            ('Nsubhalo', 'u4'),
            ('firstsubhalo', 'u4'),
            ], shape=len(g), mode='r+')

    if necessary(snap.groupfile, outarray, ['x', 'y']):
        print 'converting tab'
        if not args.dry:
            x, y, z = g['pos'].T.copy()
            cub.apply(x, y, z)
            outarray['y'] = x / width
            outarray['x'] = y / width
        
            outarray['pos'] = g['pos']
            outarray['mass'] = g['mass']
            outarray['massbytype'] = g['massbytype']
            outarray['lenbytype'] = g['lenbytype']
            outarray['Nsubhalo'] = g['nhalo']
            outarray['firstsubhalo'] = numpy.concatenate([[0], g['nhalo'].cumsum()])[:-1]
def getsubhalo(snapid):
    return dirarray(os.path.join(ROOT, '%03d' % snapid, 'subhalo'), mode='r')
def makesubhalo(snap, output):
    sub = snap.load('subhalo', 'tab')
    g = snap.readgroup()
    type = snap.load('subhalo', 'type')

    outarray = dirarray(os.path.join(output, 'subhalo'), 
        dtype=subhalodtype, shape=len(sub) - len(g), mode='r+')

    def getmask(s={}):
        if 'mask' not in s:
            s['mask'] = ~numpy.isnan(sub['mass'])
        return s['mask']

    if necessary(snap.subhalofile, outarray,
            ['x', 'y', 'lenbytype']):
        print 'converting tab'
        if not args.dry:
            mask = getmask()
            assert mask.sum() == len(outarray)
            outarray['vel'] = sub['vel'][mask]
            x, y, z = numpy.float32(sub['pos'].T)
            x = x[mask]
            y = y[mask]
            z = z[mask]
            cub.apply(x, y, z)
            outarray['x'] = y / width
            outarray['y'] = x / width
        
            outarray['pos'] = sub['pos'][mask]
            outarray['mass'] = sub['mass'][mask]
            outarray['groupid'] = sub['groupid'][mask]
            massbytype = sub['massbytype'][mask]
            outarray['iscentral'] = outarray['mass'] > 0.3 * g['mass'][outarray['groupid']]
            outarray['massbytype'] = massbytype
            outarray['lenbytype'] = sub['lenbytype'][mask]
            outarray['rcirc'] = sub['rcirc'][mask]
            outarray['vcirc'] = sub['vcirc'][mask]
            outarray['vdisp'] = sub['vdisp'][mask]
            outarray['size'] = outarray['rcirc'] / width * 10
    SRC = []
    DST = []
    for s in ['sfr', 'bhmass', 'bhmdot']:
        DST.append(s)
        SRC.append(s)

    for s in ['1500', '2000', '2500', 'Un', 'V', 'Vn', 'Vw']:
        DST.append('FAKE.%s' % s)
        SRC.append('RfFilter/FAKE.FAKE/%s' % s)

    for s in ['FUV', 'NUV']:
        DST.append('GALEX.%s' % s)
        SRC.append('RfFilter/GALEX.GALEX/%s' % s)
    for s in ['H', 'J', 'K', 'Y']:
        DST.append('UKIRT.WFCAM.%s' % s)
        SRC.append('RfFilter/UKIRT.WFCAM/%s' % s)

    for s in 'irguz':
        DST.append('SDSS.%s' % s)
        SRC.append('RfFilter/SDSS.SDSS/%s' % s)

    for src, dst in zip(SRC, DST):
        if necessary(snap.filename('subhalo', src), outarray, [dst]):
            print 'converting', src, 'to', dst
            if not args.dry:
                mask = getmask()
                outarray[dst] = snap.load('subhalo', src)[mask]
def getgroup(snapid):
    return dirarray(os.path.join(ROOT, '%03d' % snapid, 'group'), mode='r')