static int read_js_structure()

in contrib/uiuc/plugins/molfile_plugin/src/jsplugin.c [410:1002]


static int read_js_structure(void *mydata, int *optflags,
                             molfile_atom_t *atoms) {
  jshandle *js = (jshandle *) mydata;
  long i;

  if (optflags != NULL)
    *optflags = MOLFILE_NOOPTIONS; /* set to no options until we read them */

  /* read flags data from the file */
  fio_read_int32(js->fd, &js->optflags); 
  if (js->reverseendian)
    swap4_aligned(&js->optflags, 1);

#if defined(INFOMSGS)
  if (js->verbose)
    printf("jsplugin) read option flags: %0x08x\n", js->optflags);
#endif

  /* Check to see if block-based trajectory I/O is used  */
  /* and read in the block size for this file.           */
  if (js->optflags & JSOPT_TS_BLOCKIO) {
    fio_fread(&js->directio_block_size, sizeof(int), 1, js->fd);
    if (js->reverseendian)
      swap4_aligned(&js->directio_block_size, 1);

#if defined(INFOMSGS)
    if (js->verbose) {
      printf("jsplugin) Block-based I/O enabled: block size %d bytes\n", 
             js->directio_block_size);
    }
#endif

    /* Check to ensure that we can handle the block size used by the */
    /* file we are reading.  We may use variable block sizes in      */
    /* the future as more high-end filesystems begin to support      */
    /* 8KB, 16KB, or larger block sizes for enhanced sequential I/O  */
    /* performance on very large files.                              */
    if (js->directio_block_size > MOLFILE_DIRECTIO_MAX_BLOCK_SIZE) {
      printf("jsplugin) File block size exceeds jsplugin block size limit.\n");
      printf("jsplugin) Direct I/O unavailable for file '%s'\n", js->path);
    } else {
      if (fio_open(js->path, FIO_READ | FIO_DIRECT, &js->directio_fd) < 0) {
        printf("jsplugin) Direct I/O unavailable for file '%s'\n", js->path);
      } else {
        js->directio_enabled = 1;
#if defined(INFOMSGS)
        if (js->verbose) {
          printf("jsplugin) Direct I/O enabled for file '%s'\n", js->path);
        }
#endif
      } 
    }
  }

#if defined(ENABLEJSSHORTREADS)
  /* test code for an implementation that does short reads that */
  /* skip bulk solvent, useful for faster loading of very large */
  /* structures                                                 */
  if (getenv("VMDJSMAXATOMIDX") != NULL) {
    long maxatomidx = atoi(getenv("VMDJSMAXATOMIDX"));
    if (maxatomidx < 0)
      maxatomidx = 0;
    if (maxatomidx >= js->natoms)
      maxatomidx = js->natoms - 1;

    printf("jsplugin) Short-reads of timesteps enabled: %ld / %ld atoms (%.2f%%)\n",
           maxatomidx, js->natoms, 100.0*(maxatomidx+1) / ((double) js->natoms));
  }
#endif

  /* Mark the handle to indicate we've parsed the structure.             */
  /* If any errors occur after this point, they are likely fatal anyway. */
  js->parsed_structure = 1;

  /* determine whether or not this file contains structure info or not */
  if (js->optflags & JSOPT_STRUCTURE) {
    int numatomnames, numatomtypes, numresnames, numsegids, numchains;
    char **atomnames = NULL;
    char **atomtypes = NULL;
    char **resnames = NULL;
    char **segids = NULL;
    char **chains = NULL;
    short *shortbuf = NULL; /* temp buf for decoding atom records */
    int *intbuf = NULL;     /* temp buf for decoding atom records */
    float *fltbuf = NULL;   /* temp buf for decoding atom records */
 
    /* read in block of name string table sizes */
    fio_read_int32(js->fd, &numatomnames); 
    fio_read_int32(js->fd, &numatomtypes); 
    fio_read_int32(js->fd, &numresnames);
    fio_read_int32(js->fd, &numsegids);
    fio_read_int32(js->fd, &numchains); 
    if (js->reverseendian) {
      swap4_aligned(&numatomnames, 1);
      swap4_aligned(&numatomtypes, 1);
      swap4_aligned(&numresnames, 1);
      swap4_aligned(&numsegids, 1);
      swap4_aligned(&numchains, 1);
    }

#if defined(INFOMSGS)
    if (js->verbose) {
      printf("jsplugin) reading string tables...\n");
      printf("jsplugin) %d %d %d %d %d\n",
             numatomnames, numatomtypes, numresnames, numsegids, numchains);
    }
#endif

    /* skip forward to first TS if the caller gives us NULL ptrs */
    if (optflags == NULL && atoms == NULL) {
      size_t offset=0;
      offset += numatomnames * (16L * sizeof(char));
      offset += numatomtypes * (16L * sizeof(char));
      offset += numresnames  * (8L * sizeof(char));
      offset += numsegids    * (8L * sizeof(char));
      offset += numchains    * (2L * sizeof(char));
      offset += js->natoms * sizeof(short); /* atom name indices    */
      offset += js->natoms * sizeof(short); /* atom type indices    */
      offset += js->natoms * sizeof(short); /* residue name indices */
      offset += js->natoms * sizeof(short); /* segment name indices */
      offset += js->natoms * sizeof(short); /* chain name indices   */
      offset += js->natoms * sizeof(int);   /* residue indices      */
      
      /* optional per-atom fields */
      if (js->optflags & JSOPT_OCCUPANCY)
        offset += js->natoms * sizeof(float); 
      if (js->optflags & JSOPT_BFACTOR)
        offset += js->natoms * sizeof(float); 
      if (js->optflags & JSOPT_MASS)
        offset += js->natoms * sizeof(float); 
      if (js->optflags & JSOPT_CHARGE)
        offset += js->natoms * sizeof(float); 
      if (js->optflags & JSOPT_RADIUS)
        offset += js->natoms * sizeof(float); 
      if (js->optflags & JSOPT_ATOMICNUMBER)
        offset += js->natoms * sizeof(int);

      fio_fseek(js->fd, offset, FIO_SEEK_CUR);
      offset=0;

      /* these require actually seeking as we process... */
      if (js->optflags & JSOPT_BONDS) {
        fio_fread(&js->nbonds, sizeof(int), 1, js->fd);
        if (js->reverseendian)
          swap4_aligned(&js->nbonds, 1);
#if defined(INFOMSGS)
        if (js->verbose) {
          printf("jsplugin)   %d bonds...\n", js->nbonds);
        }
#endif

        offset += 2L * js->nbonds * sizeof(int);
        if (js->optflags & JSOPT_BONDORDERS)
          offset += js->nbonds * sizeof(float);

        fio_fseek(js->fd, offset, FIO_SEEK_CUR);
        offset=0;
      }

      if (js->optflags & JSOPT_ANGLES) {
        fio_fread(&js->numangles, sizeof(int), 1, js->fd);
        if (js->reverseendian)
          swap4_aligned(&js->numangles, 1);
#if defined(INFOMSGS)
        if (js->verbose) {
          printf("jsplugin)   %d angles...\n", js->numangles);
        }
#endif
        fio_fseek(js->fd, sizeof(int)*3L*js->numangles, FIO_SEEK_CUR);

        fio_fread(&js->numdihedrals, sizeof(int), 1, js->fd);
        if (js->reverseendian)
          swap4_aligned(&js->numdihedrals, 1);
#if defined(INFOMSGS)
        printf("jsplugin)   %d dihedrals...\n", js->numdihedrals);
#endif
        fio_fseek(js->fd, sizeof(int)*4L*js->numdihedrals, FIO_SEEK_CUR);

        fio_fread(&js->numimpropers, sizeof(int), 1, js->fd);
        if (js->reverseendian)
          swap4_aligned(&js->numimpropers, 1);
#if defined(INFOMSGS)
        if (js->verbose) {
          printf("jsplugin)   %d impropers...\n", js->numimpropers);
        }
#endif
        fio_fseek(js->fd, sizeof(int)*4L*js->numimpropers, FIO_SEEK_CUR);
      }

      if (js->optflags & JSOPT_CTERMS) {
        fio_fread(&js->numcterms, sizeof(int), 1, js->fd);
        if (js->reverseendian)
          swap4_aligned(&js->numcterms, 1);
#if defined(INFOMSGS)
        if (js->verbose) {
          printf("jsplugin)   %d cterms...\n", js->numcterms);
        }
#endif
        fio_fseek(js->fd, sizeof(int)*8L*js->numcterms, FIO_SEEK_CUR);
      }
  
      /* record the file offset for the first timestep */
      js_calc_timestep_blocking_info(js);

      return MOLFILE_SUCCESS;
    }


    /* allocate string tables */
    atomnames = (char **) malloc(numatomnames * sizeof(char *));
    atomtypes = (char **) malloc(numatomtypes * sizeof(char *));
    resnames  = (char **) malloc(numresnames  * sizeof(char *));
    segids    = (char **) malloc(numsegids    * sizeof(char *));
    chains    = (char **) malloc(numchains    * sizeof(char *));

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   atom names...\n");
#endif

    /* read in the string tables */
    for (i=0; i<numatomnames; i++) {
      atomnames[i] = (char *) malloc(16L * sizeof(char));
      fio_fread(atomnames[i], 16L * sizeof(char), 1, js->fd);
    }

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   atom types...\n");
#endif
    for (i=0; i<numatomtypes; i++) {
      atomtypes[i] = (char *) malloc(16L * sizeof(char));
      fio_fread(atomtypes[i], 16L * sizeof(char), 1, js->fd);
    }

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   residue names...\n");
#endif
    for (i=0; i<numresnames; i++) {
      resnames[i] = (char *) malloc(8L * sizeof(char));
      fio_fread(resnames[i], 8L * sizeof(char), 1, js->fd);
    }

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   segment names...\n");
#endif
    for (i=0; i<numsegids; i++) {
      segids[i] = (char *) malloc(8L * sizeof(char));
      fio_fread(segids[i], 8L * sizeof(char), 1, js->fd);
    }

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   chain names...\n");
#endif
    for (i=0; i<numchains; i++) {
      chains[i] = (char *) malloc(2L * sizeof(char));
      fio_fread(chains[i], 2L * sizeof(char), 1, js->fd);
    }

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin) reading numeric field tables...\n");
#endif
    /* read in all of the atom fields */
    shortbuf = (short *) malloc(js->natoms * sizeof(short));

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   atom name indices...\n");
#endif
    /* read in atom names */
    fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
    if (js->reverseendian)
      swap2_aligned(shortbuf, js->natoms);
    for (i=0; i<js->natoms; i++) {
      strcpy(atoms[i].name, atomnames[shortbuf[i]]);
    }
    for (i=0; i<numatomnames; i++)
      free(atomnames[i]);
    free(atomnames);

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   atom type indices...\n");
#endif
    /* read in atom types */
    fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
    if (js->reverseendian)
      swap2_aligned(shortbuf, js->natoms);
    for (i=0; i<js->natoms; i++) {
      strcpy(atoms[i].type, atomtypes[shortbuf[i]]);
    }
    for (i=0; i<numatomtypes; i++)
      free(atomtypes[i]);
    free(atomtypes);

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   residue name indices...\n");
#endif
    /* read in resnames */
    fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
    if (js->reverseendian)
      swap2_aligned(shortbuf, js->natoms);
    for (i=0; i<js->natoms; i++) {
      strcpy(atoms[i].resname, resnames[shortbuf[i]]);
    }
    for (i=0; i<numresnames; i++)
      free(resnames[i]);
    free(resnames);
    
#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   segment name indices...\n");
#endif
    /* read in segids */
    fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
    if (js->reverseendian)
      swap2_aligned(shortbuf, js->natoms);
    for (i=0; i<js->natoms; i++) {
      strcpy(atoms[i].segid, segids[shortbuf[i]]);
    }
    for (i=0; i<numsegids; i++)
      free(segids[i]);
    free(segids);

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   chain name indices...\n");
#endif
    /* read in chains */
    fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
    if (js->reverseendian)
      swap2_aligned(shortbuf, js->natoms);
    for (i=0; i<js->natoms; i++) {
      strcpy(atoms[i].chain, chains[shortbuf[i]]);
    }
    for (i=0; i<numchains; i++)
      free(chains[i]);
    free(chains);

    if (shortbuf != NULL) {
      free(shortbuf);
      shortbuf=NULL;
    }

    /* 
     * read in integer data blocks 
     */
    intbuf = (int *) malloc(js->natoms * sizeof(int));

#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin)   residue indices...\n");
#endif
    /* read in resid */
    fio_fread(intbuf, js->natoms * sizeof(int), 1, js->fd);
    if (js->reverseendian)
      swap4_aligned(intbuf, js->natoms);
    for (i=0; i<js->natoms; i++) {
      atoms[i].resid = intbuf[i];
    }    
     
    if (intbuf != NULL) {
      free(intbuf);
      intbuf = NULL;
    }


#if defined(INFOMSGS)
    if (js->verbose)
      printf("jsplugin) reading optional per-atom tables...\n");
#endif
    /*
     * read in optional single-precision float data blocks
     */ 
    if (js->optflags & (JSOPT_OCCUPANCY | JSOPT_BFACTOR | 
        JSOPT_MASS | JSOPT_RADIUS | JSOPT_CHARGE)) 
      fltbuf = (float *) malloc(js->natoms * sizeof(float));

    /* read in optional data if it exists */
    if (js->optflags & JSOPT_OCCUPANCY) {
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   occupancy...\n");
#endif
      *optflags |= MOLFILE_OCCUPANCY;
      fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(fltbuf, js->natoms);
      for (i=0; i<js->natoms; i++) {
        atoms[i].occupancy = fltbuf[i];
      }    
    }

    if (js->optflags & JSOPT_BFACTOR) {
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   bfactor...\n");
#endif
      *optflags |= MOLFILE_BFACTOR;
      fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(fltbuf, js->natoms);
      for (i=0; i<js->natoms; i++) {
        atoms[i].bfactor = fltbuf[i];
      }    
    }

    if (js->optflags & JSOPT_MASS) { 
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   mass...\n");
#endif
      *optflags |= MOLFILE_MASS;
      fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(fltbuf, js->natoms);
      for (i=0; i<js->natoms; i++) {
        atoms[i].mass = fltbuf[i];
      }    
    }

    if (js->optflags & JSOPT_CHARGE) { 
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   charge...\n");
#endif
      *optflags |= MOLFILE_CHARGE;
      fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(fltbuf, js->natoms);
      for (i=0; i<js->natoms; i++) {
        atoms[i].charge = fltbuf[i];
      }    
    }

    if (js->optflags & JSOPT_RADIUS) { 
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   radius...\n");
#endif
      *optflags |= MOLFILE_RADIUS;
      fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(fltbuf, js->natoms);
      for (i=0; i<js->natoms; i++) {
        atoms[i].radius = fltbuf[i];
      }    
    }

    if (fltbuf != NULL) {
      free(fltbuf);
      fltbuf=NULL;
    }

    /*
     * read in optional integer data blocks
     */ 
    if (js->optflags & JSOPT_ATOMICNUMBER)
      intbuf = (int *) malloc(js->natoms * sizeof(int));

    if (js->optflags & JSOPT_ATOMICNUMBER) { 
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   atomic number...\n");
#endif
      *optflags |= MOLFILE_ATOMICNUMBER;
      fio_fread(intbuf, js->natoms * sizeof(int), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(intbuf, js->natoms);
      for (i=0; i<js->natoms; i++) {
        atoms[i].atomicnumber = intbuf[i];
      }    
    }

    if (intbuf != NULL) {
      free(intbuf);
      intbuf = NULL;
    }


    /*
     * read in bonds and fractional bond orders
     */ 
    if (js->optflags & JSOPT_BONDS) {
      fio_fread(&js->nbonds, sizeof(int), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(&js->nbonds, 1);
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   %d bonds...\n", js->nbonds);
#endif

      js->bondfrom = (int *) malloc(js->nbonds * sizeof(int));
      js->bondto = (int *) malloc(js->nbonds * sizeof(int));
      fio_fread(js->bondfrom, js->nbonds * sizeof(int), 1, js->fd);
      fio_fread(js->bondto, js->nbonds * sizeof(int), 1, js->fd);
      if (js->reverseendian) {
        swap4_aligned(js->bondfrom, js->nbonds);
        swap4_aligned(js->bondto, js->nbonds);
      }

      if (js->optflags & JSOPT_BONDORDERS) {
#if defined(INFOMSGS)
        if (js->verbose)
          printf("jsplugin)   bond orders...\n");
#endif
        js->bondorders = (float *) malloc(js->nbonds * sizeof(float));
        fio_fread(js->bondorders, js->nbonds * sizeof(float), 1, js->fd);
        if (js->reverseendian)
          swap4_aligned(js->bondorders, js->nbonds);
      }
    }

    if (js->optflags & JSOPT_ANGLES) {
      fio_fread(&js->numangles, sizeof(int), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(&js->numangles, 1);
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   %d angles...\n", js->numangles);
#endif
      js->angles = (int *) malloc(3L * js->numangles * sizeof(int));
      fio_fread(js->angles, sizeof(int)*3L*js->numangles, 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(js->angles, 3L*js->numangles);

      fio_fread(&js->numdihedrals, sizeof(int), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(&js->numdihedrals, 1);
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   %d dihedrals...\n", js->numdihedrals);
#endif
      js->dihedrals = (int *) malloc(4L * js->numdihedrals * sizeof(int));
      fio_fread(js->dihedrals, sizeof(int)*4L*js->numdihedrals, 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(js->dihedrals, 4L*js->numdihedrals);

      fio_fread(&js->numimpropers, sizeof(int), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(&js->numimpropers, 1);
      js->impropers = (int *) malloc(4L * js->numimpropers * sizeof(int));
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   %d impropers...\n", js->numimpropers);
#endif
      fio_fread(js->impropers, sizeof(int)*4L*js->numimpropers, 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(js->impropers, 4L*js->numimpropers);
    }
    if (js->optflags & JSOPT_CTERMS) {
      fio_fread(&js->numcterms, sizeof(int), 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(&js->numcterms, 1);
      js->cterms = (int *) malloc(8L * js->numcterms * sizeof(int));
#if defined(INFOMSGS)
      if (js->verbose)
        printf("jsplugin)   %d cterms...\n", js->numcterms);
#endif
      fio_fread(js->cterms, sizeof(int)*8L*js->numcterms, 1, js->fd);
      if (js->reverseendian)
        swap4_aligned(js->cterms, 8L*js->numcterms);
    }

#if defined(INFOMSGS)
    if (js->verbose) {
      printf("jsplugin) final optflags: %08x\n", *optflags);
      printf("jsplugin) structure information complete\n");
    }
#endif

    /* record the file offset for the first timestep */
    js_calc_timestep_blocking_info(js);

    return MOLFILE_SUCCESS;
  }

#if defined(INFOMSGS)
  if (js->verbose)
    printf("jsplugin) no structure information available\n");
#endif

  /* record the file offset for the first timestep */
  js_calc_timestep_blocking_info(js);

  /* else, we have no structure information */
  return MOLFILE_NOSTRUCTUREDATA;
}