Beispiel #1
0
static void *open_tng_read(const char *filename, const char*,
                           int *natoms)
{
    tngdata *tng;
    tng_function_status stat;
    int64_t n, exp;

    tng = new tngdata;

    stat = tng_util_trajectory_open(filename, 'r', &tng->tng_traj);
    if(stat != TNG_SUCCESS)
    {
        fprintf(stderr, "tngplugin) Cannot open file '%s'\n", filename);
        return NULL;
    }

    tng_num_particles_get(tng->tng_traj, &n);
    *natoms = (int)n;
    tng->natoms = (int)n;
    tng->step = 0;
    tng_num_frames_get(tng->tng_traj, &n);
    tng->n_frames = n;
    tng->has_velocities = 0;

    tng_distance_unit_exponential_get(tng->tng_traj, &exp);
    tng->coord_exponential = (int) exp;


    return tng;
}
Beispiel #2
0
void gmx_fwrite_tng(tng_trajectory_t tng,
                    const gmx_bool   bUseLossyCompression,
                    int              step,
                    real             elapsedPicoSeconds,
                    real             lambda,
                    const rvec      *box,
                    int              nAtoms,
                    const rvec      *x,
                    const rvec      *v,
                    const rvec      *f)
{
#ifdef GMX_USE_TNG
    typedef tng_function_status (*write_data_func_pointer)(tng_trajectory_t,
                                                           const gmx_int64_t,
                                                           const double,
                                                           const real*,
                                                           const gmx_int64_t,
                                                           const gmx_int64_t,
                                                           const char*,
                                                           const char,
                                                           const char);
#ifdef GMX_DOUBLE
    static write_data_func_pointer           write_data           = tng_util_generic_with_time_double_write;
#else
    static write_data_func_pointer           write_data           = tng_util_generic_with_time_write;
#endif
    double                                   elapsedSeconds = elapsedPicoSeconds * PICO;
    gmx_int64_t                              nParticles;
    char                                     compression;


    if (!tng)
    {
        /* This function might get called when the type of the
           compressed trajectory is actually XTC. So we exit and move
           on. */
        return;
    }

    tng_num_particles_get(tng, &nParticles);
    if (nAtoms != (int)nParticles)
    {
        tng_implicit_num_particles_set(tng, nAtoms);
    }

    if (bUseLossyCompression)
    {
        compression = TNG_TNG_COMPRESSION;
    }
    else
    {
        compression = TNG_GZIP_COMPRESSION;
    }

    /* The writing is done using write_data, which writes float or double
     * depending on the GROMACS compilation. */
    if (x)
    {
        GMX_ASSERT(box, "Need a non-NULL box if positions are written");

        if (write_data(tng, step, elapsedSeconds,
                       reinterpret_cast<const real *>(x),
                       3, TNG_TRAJ_POSITIONS, "POSITIONS",
                       TNG_PARTICLE_BLOCK_DATA,
                       compression) != TNG_SUCCESS)
        {
            gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?");
        }
        /* TNG-MF1 compression only compresses positions and velocities. Use lossless
         * compression for box shape regardless of output mode */
        if (write_data(tng, step, elapsedSeconds,
                       reinterpret_cast<const real *>(box),
                       9, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
                       TNG_NON_PARTICLE_BLOCK_DATA,
                       TNG_GZIP_COMPRESSION) != TNG_SUCCESS)
        {
            gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?");
        }
    }

    if (v)
    {
        if (write_data(tng, step, elapsedSeconds,
                       reinterpret_cast<const real *>(v),
                       3, TNG_TRAJ_VELOCITIES, "VELOCITIES",
                       TNG_PARTICLE_BLOCK_DATA,
                       compression) != TNG_SUCCESS)
        {
            gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?");
        }
    }

    if (f)
    {
        /* TNG-MF1 compression only compresses positions and velocities. Use lossless
         * compression for forces regardless of output mode */
        if (write_data(tng, step, elapsedSeconds,
                       reinterpret_cast<const real *>(f),
                       3, TNG_TRAJ_FORCES, "FORCES",
                       TNG_PARTICLE_BLOCK_DATA,
                       TNG_GZIP_COMPRESSION) != TNG_SUCCESS)
        {
            gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?");
        }
    }

    /* TNG-MF1 compression only compresses positions and velocities. Use lossless
     * compression for lambdas regardless of output mode */
    if (write_data(tng, step, elapsedSeconds,
                   reinterpret_cast<const real *>(&lambda),
                   1, TNG_GMX_LAMBDA, "LAMBDAS",
                   TNG_NON_PARTICLE_BLOCK_DATA,
                   TNG_GZIP_COMPRESSION) != TNG_SUCCESS)
    {
        gmx_file("Cannot write TNG trajectory frame; maybe you are out of disk space?");
    }
#else
    GMX_UNUSED_VALUE(tng);
    GMX_UNUSED_VALUE(bUseLossyCompression);
    GMX_UNUSED_VALUE(step);
    GMX_UNUSED_VALUE(elapsedPicoSeconds);
    GMX_UNUSED_VALUE(lambda);
    GMX_UNUSED_VALUE(box);
    GMX_UNUSED_VALUE(nAtoms);
    GMX_UNUSED_VALUE(x);
    GMX_UNUSED_VALUE(v);
    GMX_UNUSED_VALUE(f);
#endif
}
Beispiel #3
0
static int read_tng_timestep(void *v, int natoms, molfile_timestep_t *ts)
{
    /* The pointers that will be allocated by the TNG must be NULL before allocation. */
    void *values = 0;
    char datatype;
    float box_shape[9], vmd_box[6];
    float fact = 1;
    int64_t frame, n, temp, temp2;
    double temp_time;
    tng_function_status stat;
    tngdata *tng = (tngdata *)v;

    if(!ts)
    {
        return MOLFILE_ERROR;
    }

//     fprintf(stderr, "Reading framestep from TNG\n");

    stat = tng_util_particle_data_next_frame_read(tng->tng_traj, TNG_TRAJ_POSITIONS, &values,
                                                  &datatype, &frame, &temp_time);
    ts->physical_time = temp_time / PICO;
    if(stat != TNG_SUCCESS)
    {
        if(values)
        {
            free(values);
        }
        return MOLFILE_ERROR;
    }
//     fprintf(stderr, "tngplugin) Timestep %d (%f), frame %d (%d), %d atoms\n",
//             tng->step, ts->physical_time, (int)frame, (int)tng->n_frames, natoms);

    /* TODO: Here it would be possible to add reading of the energy and pressure
     * measurements supported in VMD if they are present in the TNG file */
    tng_num_particles_get(tng->tng_traj, &n);
    if(n != natoms)
    {
        fprintf(stderr, "tngplugin) Timestep in file contains wrong number of atoms\n");
        fprintf(stderr, "tngplugin) Found %d, expected %d\n", (int)n, natoms);
        return MOLFILE_ERROR;
    }

    if(tng->coord_exponential != -10)
    {
        fact = pow(10.0, tng->coord_exponential + 10);
    }

    convert_to_float(values, ts->coords, fact, natoms, 3, datatype);

    if(ts->velocities)
    {
//         fprintf(stderr, "tngplugin) Reading velocities\n");
        stat = tng_particle_data_vector_interval_get(tng->tng_traj, TNG_TRAJ_VELOCITIES, frame,
                                                     frame, TNG_USE_HASH, &values,
                                                     &n, &temp, &temp2, &datatype);
        if(stat == TNG_CRITICAL)
        {
            if(values)
            {
                free(values);
            }
            return MOLFILE_ERROR;
        }
        if(stat == TNG_SUCCESS)
        {
            convert_to_float(values, ts->velocities, fact, natoms, 3, datatype);
        }
    }

    stat = tng_data_vector_interval_get(tng->tng_traj, TNG_TRAJ_BOX_SHAPE,
                                        frame, frame, TNG_USE_HASH, &values,
                                        &temp, &temp2, &datatype);
    if(stat == TNG_CRITICAL)
    {
        if(values)
        {
            free(values);
        }
        return MOLFILE_ERROR;
    }
    if(stat == TNG_SUCCESS)
    {
        convert_to_float(values, box_shape, fact, 1, 9, datatype);

        convert_tng_box_shape_to_vmd(box_shape, vmd_box);
        if(ts)
        {
            ts->A = vmd_box[0];
            ts->B = vmd_box[1];
            ts->C = vmd_box[2];
            ts->alpha = vmd_box[3];
            ts->beta = vmd_box[4];
            ts->gamma = vmd_box[5];
        }
    }

    ++tng->step;
    if(values)
    {
        free(values);
    }

    return MOLFILE_SUCCESS;
}
gmx_bool gmx_get_tng_data_next_frame_of_block_type(tng_trajectory_t     input,
                                                   gmx_int64_t          blockId,
                                                   real               **values,
                                                   gmx_int64_t         *frameNumber,
                                                   double              *frameTime,
                                                   gmx_int64_t         *nValuesPerFrame,
                                                   gmx_int64_t         *nAtoms,
                                                   real                *prec,
                                                   char                *name,
                                                   int                  maxLen,
                                                   gmx_bool            *bOK)
{
#if GMX_USE_TNG
    tng_function_status stat;
    char                datatype = -1;
    gmx_int64_t         codecId;
    int                 blockDependency;
    void               *data = 0;
    double              localPrec;

    stat = tng_data_block_name_get(input, blockId, name, maxLen);
    if (stat != TNG_SUCCESS)
    {
        gmx_file("Cannot read next frame of TNG file");
    }
    stat = tng_data_block_dependency_get(input, blockId, &blockDependency);
    if (stat != TNG_SUCCESS)
    {
        gmx_file("Cannot read next frame of TNG file");
    }
    if (blockDependency & TNG_PARTICLE_DEPENDENT)
    {
        tng_num_particles_get(input, nAtoms);
        stat = tng_util_particle_data_next_frame_read(input,
                                                      blockId,
                                                      &data,
                                                      &datatype,
                                                      frameNumber,
                                                      frameTime);
    }
    else
    {
        *nAtoms = 1; /* There are not actually any atoms, but it is used for
                        allocating memory */
        stat    = tng_util_non_particle_data_next_frame_read(input,
                                                             blockId,
                                                             &data,
                                                             &datatype,
                                                             frameNumber,
                                                             frameTime);
    }
    if (stat == TNG_CRITICAL)
    {
        gmx_file("Cannot read next frame of TNG file");
    }
    if (stat == TNG_FAILURE)
    {
        *bOK = TRUE;
        return FALSE;
    }

    stat = tng_data_block_num_values_per_frame_get(input, blockId, nValuesPerFrame);
    if (stat != TNG_SUCCESS)
    {
        gmx_file("Cannot read next frame of TNG file");
    }
    snew(*values, sizeof(real) * *nValuesPerFrame * *nAtoms);
    convert_array_to_real_array(data,
                                *values,
                                getDistanceScaleFactor(input),
                                *nAtoms,
                                *nValuesPerFrame,
                                datatype);

    tng_util_frame_current_compression_get(input, blockId, &codecId, &localPrec);

    /* This must be updated if/when more lossy compression methods are added */
    if (codecId != TNG_TNG_COMPRESSION)
    {
        *prec = -1.0;
    }
    else
    {
        *prec = localPrec;
    }

    *bOK = TRUE;
    return TRUE;
#else
    GMX_UNUSED_VALUE(input);
    GMX_UNUSED_VALUE(blockId);
    GMX_UNUSED_VALUE(values);
    GMX_UNUSED_VALUE(frameNumber);
    GMX_UNUSED_VALUE(frameTime);
    GMX_UNUSED_VALUE(nValuesPerFrame);
    GMX_UNUSED_VALUE(nAtoms);
    GMX_UNUSED_VALUE(prec);
    GMX_UNUSED_VALUE(name);
    GMX_UNUSED_VALUE(maxLen);
    GMX_UNUSED_VALUE(bOK);
    return FALSE;
#endif
}
/* TODO: If/when TNG acquires the ability to copy data blocks without
 * uncompressing them, then this implemenation should be reconsidered.
 * Ideally, gmx trjconv -f a.tng -o b.tng -b 10 -e 20 would be fast
 * and lose no information. */
gmx_bool gmx_read_next_tng_frame(tng_trajectory_t            input,
                                 t_trxframe                 *fr,
                                 gmx_int64_t                *requestedIds,
                                 int                         numRequestedIds)
{
#if GMX_USE_TNG
    gmx_bool                bOK = TRUE;
    tng_function_status     stat;
    gmx_int64_t             numberOfAtoms = -1, frameNumber = -1;
    gmx_int64_t             nBlocks, blockId, *blockIds = NULL, codecId;
    char                    datatype      = -1;
    void                   *values        = NULL;
    double                  frameTime     = -1.0;
    int                     size, blockDependency;
    double                  prec;
    const int               defaultNumIds = 5;
    static gmx_int64_t      fallbackRequestedIds[defaultNumIds] =
    {
        TNG_TRAJ_BOX_SHAPE, TNG_TRAJ_POSITIONS,
        TNG_TRAJ_VELOCITIES, TNG_TRAJ_FORCES,
        TNG_GMX_LAMBDA
    };


    fr->bStep     = FALSE;
    fr->bTime     = FALSE;
    fr->bLambda   = FALSE;
    fr->bAtoms    = FALSE;
    fr->bPrec     = FALSE;
    fr->bX        = FALSE;
    fr->bV        = FALSE;
    fr->bF        = FALSE;
    fr->bBox      = FALSE;

    /* If no specific IDs were requested read all block types that can
     * currently be interpreted */
    if (!requestedIds || numRequestedIds == 0)
    {
        numRequestedIds = defaultNumIds;
        requestedIds    = fallbackRequestedIds;
    }

    stat = tng_num_particles_get(input, &numberOfAtoms);
    if (stat != TNG_SUCCESS)
    {
        gmx_file("Cannot determine number of atoms from TNG file.");
    }
    fr->natoms = numberOfAtoms;

    if (!gmx_get_tng_data_block_types_of_next_frame(input,
                                                    fr->step,
                                                    numRequestedIds,
                                                    requestedIds,
                                                    &frameNumber,
                                                    &nBlocks,
                                                    &blockIds))
    {
        return FALSE;
    }

    if (nBlocks == 0)
    {
        return FALSE;
    }

    for (gmx_int64_t i = 0; i < nBlocks; i++)
    {
        blockId = blockIds[i];
        tng_data_block_dependency_get(input, blockId, &blockDependency);
        if (blockDependency & TNG_PARTICLE_DEPENDENT)
        {
            stat = tng_util_particle_data_next_frame_read(input,
                                                          blockId,
                                                          &values,
                                                          &datatype,
                                                          &frameNumber,
                                                          &frameTime);
        }
        else
        {
            stat = tng_util_non_particle_data_next_frame_read(input,
                                                              blockId,
                                                              &values,
                                                              &datatype,
                                                              &frameNumber,
                                                              &frameTime);
        }
        if (stat == TNG_CRITICAL)
        {
            gmx_file("Cannot read positions from TNG file.");
            return FALSE;
        }
        else if (stat == TNG_FAILURE)
        {
            continue;
        }
        switch (blockId)
        {
            case TNG_TRAJ_BOX_SHAPE:
                switch (datatype)
                {
                    case TNG_INT_DATA:
                        size = sizeof(gmx_int64_t);
                        break;
                    case TNG_FLOAT_DATA:
                        size = sizeof(float);
                        break;
                    case TNG_DOUBLE_DATA:
                        size = sizeof(double);
                        break;
                    default:
                        gmx_incons("Illegal datatype of box shape values!");
                }
                for (int i = 0; i < DIM; i++)
                {
                    convert_array_to_real_array(reinterpret_cast<char *>(values) + size * i * DIM,
                                                reinterpret_cast<real *>(fr->box[i]),
                                                getDistanceScaleFactor(input),
                                                1,
                                                DIM,
                                                datatype);
                }
                fr->bBox = TRUE;
                break;
            case TNG_TRAJ_POSITIONS:
                srenew(fr->x, fr->natoms);
                convert_array_to_real_array(values,
                                            reinterpret_cast<real *>(fr->x),
                                            getDistanceScaleFactor(input),
                                            fr->natoms,
                                            DIM,
                                            datatype);
                fr->bX = TRUE;
                tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
                /* This must be updated if/when more lossy compression methods are added */
                if (codecId == TNG_TNG_COMPRESSION)
                {
                    fr->prec  = prec;
                    fr->bPrec = TRUE;
                }
                break;
            case TNG_TRAJ_VELOCITIES:
                srenew(fr->v, fr->natoms);
                convert_array_to_real_array(values,
                                            (real *) fr->v,
                                            getDistanceScaleFactor(input),
                                            fr->natoms,
                                            DIM,
                                            datatype);
                fr->bV = TRUE;
                tng_util_frame_current_compression_get(input, blockId, &codecId, &prec);
                /* This must be updated if/when more lossy compression methods are added */
                if (codecId == TNG_TNG_COMPRESSION)
                {
                    fr->prec  = prec;
                    fr->bPrec = TRUE;
                }
                break;
            case TNG_TRAJ_FORCES:
                srenew(fr->f, fr->natoms);
                convert_array_to_real_array(values,
                                            reinterpret_cast<real *>(fr->f),
                                            getDistanceScaleFactor(input),
                                            fr->natoms,
                                            DIM,
                                            datatype);
                fr->bF = TRUE;
                break;
            case TNG_GMX_LAMBDA:
                switch (datatype)
                {
                    case TNG_FLOAT_DATA:
                        fr->lambda = *(reinterpret_cast<float *>(values));
                        break;
                    case TNG_DOUBLE_DATA:
                        fr->lambda = *(reinterpret_cast<double *>(values));
                        break;
                    default:
                        gmx_incons("Illegal datatype lambda value!");
                }
                fr->bLambda = TRUE;
                break;
            default:
                gmx_warning("Illegal block type! Currently GROMACS tools can only handle certain data types. Skipping block.");
        }
        /* values does not have to be freed before reading next frame. It will
         * be reallocated if it is not NULL. */
    }

    fr->step  = static_cast<int>(frameNumber);
    fr->bStep = TRUE;
    // Convert the time to ps
    fr->time  = frameTime / PICO;
    fr->bTime = TRUE;

    /* values must be freed before leaving this function */
    sfree(values);

    return bOK;
#else
    GMX_UNUSED_VALUE(input);
    GMX_UNUSED_VALUE(fr);
    GMX_UNUSED_VALUE(requestedIds);
    GMX_UNUSED_VALUE(numRequestedIds);
    return FALSE;
#endif
}
void gmx_tng_setup_atom_subgroup(tng_trajectory_t tng,
                                 const int        nind,
                                 const int       *ind,
                                 const char      *name)
{
#if GMX_USE_TNG
    gmx_int64_t              nAtoms, cnt, nMols;
    tng_molecule_t           mol, iterMol;
    tng_chain_t              chain;
    tng_residue_t            res;
    tng_atom_t               atom;
    tng_function_status      stat;

    tng_num_particles_get(tng, &nAtoms);

    if (nAtoms == nind)
    {
        return;
    }

    stat = tng_molecule_find(tng, name, -1, &mol);
    if (stat == TNG_SUCCESS)
    {
        tng_molecule_num_atoms_get(tng, mol, &nAtoms);
        tng_molecule_cnt_get(tng, mol, &cnt);
        if (nAtoms == nind)
        {
            stat = TNG_SUCCESS;
        }
        else
        {
            stat = TNG_FAILURE;
        }
    }
    if (stat == TNG_FAILURE)
    {
        /* The indexed atoms are added to one separate molecule. */
        tng_molecule_alloc(tng, &mol);
        tng_molecule_name_set(tng, mol, name);
        tng_molecule_chain_add(tng, mol, "", &chain);

        for (int i = 0; i < nind; i++)
        {
            char        temp_name[256], temp_type[256];

            /* Try to retrieve the residue name of the atom */
            stat = tng_residue_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
            if (stat != TNG_SUCCESS)
            {
                temp_name[0] = '\0';
            }
            /* Check if the molecule of the selection already contains this residue */
            if (tng_chain_residue_find(tng, chain, temp_name, -1, &res)
                != TNG_SUCCESS)
            {
                tng_chain_residue_add(tng, chain, temp_name, &res);
            }
            /* Try to find the original name and type of the atom */
            stat = tng_atom_name_of_particle_nr_get(tng, ind[i], temp_name, 256);
            if (stat != TNG_SUCCESS)
            {
                temp_name[0] = '\0';
            }
            stat = tng_atom_type_of_particle_nr_get(tng, ind[i], temp_type, 256);
            if (stat != TNG_SUCCESS)
            {
                temp_type[0] = '\0';
            }
            tng_residue_atom_w_id_add(tng, res, temp_name, temp_type, ind[i], &atom);
        }
        tng_molecule_existing_add(tng, &mol);
    }
    /* Set the count of the molecule containing the selected atoms to 1 and all
     * other molecules to 0 */
    tng_molecule_cnt_set(tng, mol, 1);
    tng_num_molecule_types_get(tng, &nMols);
    for (gmx_int64_t k = 0; k < nMols; k++)
    {
        tng_molecule_of_index_get(tng, k, &iterMol);
        if (iterMol == mol)
        {
            continue;
        }
        tng_molecule_cnt_set(tng, iterMol, 0);
    }
#else
    GMX_UNUSED_VALUE(tng);
    GMX_UNUSED_VALUE(nind);
    GMX_UNUSED_VALUE(ind);
    GMX_UNUSED_VALUE(name);
#endif
}