cp[0] = w[3]; cp[1] = w[2]; cp[2] = w[1]; cp[3] = w[0];
}
+static void
+s_Swap8(char *cp)
+{
+ char w[8];
+ w[0] = cp[0]; w[1] = cp[1]; w[2] = cp[2]; w[3] = cp[3]; w[4] = cp[4]; w[5] = cp[5]; w[6] = cp[6]; w[7] = cp[7];
+ cp[0] = w[7]; cp[1] = w[6]; cp[2] = w[5]; cp[3] = w[4]; cp[4] = w[3]; cp[5] = w[2]; cp[6] = w[1]; cp[7] = w[0];
+}
+
#define s_SwapInt32(ip) s_Swap4((char *)(ip))
#define s_SwapSFloat32(fp) s_Swap4((char *)(fp))
}
static int
+s_Write8(int fd, const char *cp, int swap)
+{
+ if (swap) {
+ char w[8];
+ w[7] = cp[0]; w[6] = cp[1]; w[5] = cp[2]; w[4] = cp[3]; w[3] = cp[4]; w[2] = cp[5]; w[1] = cp[6]; w[0] = cp[7];
+ return write(fd, w, 8);
+ } else return write(fd, cp, 8);
+}
+
+static int
s_WriteInt32(DcdRecord *dcd, Int32 i)
{
return (s_Write4(dcd->fd, (const char *)(&i), dcd->reverse_endian) == 4);
}
static int
+s_WriteSFloat64(DcdRecord *dcd, SFloat64 d)
+{
+ return (s_Write8(dcd->fd, (const char *)(&d), dcd->reverse_endian) == 8);
+}
+
+static int
s_WriteZeros(int fd, int count)
{
char buf[128];
{
Int32 nn, nnn;
char buf[5];
-
+ char delta_buf[8];
+
if (dr == NULL)
return -1; /* Internal error */
memset(dr, 0, sizeof(DcdRecord));
if (dr->fd < 0)
return -2; /* Cannot open file */
- /* Section 1: 'CORD', NFILE, NPRIV, NSAVC, NSTEP, 5*ZERO, DELTA, */
- /* WITH_UNITCELL, 4*ZERO, 24 */
+ /* Section 1: 'CORD', NFILE, NPRIV, NSAVC, NSTEP, 4*ZERO, NFIX, */
+ /* DELTA (4 bytes for charmm format, 8 bytes for x-plor format), */
+ /* NEXTRA (charmm only), N4DIM, 6*ZERO, NCHARM, 24 */
if (!s_ReadInt32(dr, &nn))
return 1; /* Bad format: premature EOF */
if (nn != 84) {
s_ReadInt32(dr, &(dr->nstart));
s_ReadInt32(dr, &(dr->ninterval));
s_ReadInt32(dr, &(dr->nend));
- lseek(dr->fd, 20, SEEK_CUR); /* Skip 5 zeros */
- s_ReadSFloat32(dr, &(dr->delta));
- s_ReadInt32(dr, &(dr->with_unitcell));
- lseek(dr->fd, 32, SEEK_CUR); /* Skip 8 zeros */
- s_ReadInt32(dr, &nn); /* This should be 24 */
- if (nn != 24)
- return 4; /* Bad format: bad end of first section */
+ lseek(dr->fd, 16, SEEK_CUR); /* Skip 4 zeros */
+ s_ReadInt32(dr, &(dr->nfix));
+ read(dr->fd, delta_buf, 8); /* If charmm format, then this is { float; int32; } otherwise this is a double */
+ s_ReadInt32(dr, &(dr->n4dim));
+ lseek(dr->fd, 28, SEEK_CUR); /* Skip 7 zeros */
+ s_ReadInt32(dr, &(dr->ncharmver));
s_ReadInt32(dr, &nn); /* This should be 84 */
if (nn != 84)
return 4;
+ if (dr->ncharmver == 0) {
+ if (dr->reverse_endian)
+ s_Swap8(delta_buf);
+ dr->delta = *((SFloat64 *)delta_buf);
+ dr->nextra = 0;
+ } else {
+ if (dr->reverse_endian) {
+ s_Swap4(delta_buf);
+ s_Swap4(delta_buf + 4);
+ }
+ dr->delta = *((SFloat32 *)delta_buf);
+ dr->nextra = *((Int32 *)(delta_buf + 4));
+ }
/* Section 2: Title lines */
if (!s_ReadInt32(dr, &nn) || lseek(dr->fd, nn, SEEK_CUR) < 0 || !s_ReadInt32(dr, &nnn) || nn != nnn)
return -2; /* Cannot create file */
memset(buf, ' ', 80);
- /* Section 1: 'CORD', NFILE, NPRIV, NSAVC, NSTEP, 5*ZERO, DELTA, */
- /* WITH_UNITCELL, 8*ZERO, 24 (92 bytes) */
+ /* Section 1: 'CORD', NFILE, NPRIV, NSAVC, NSTEP, 4*ZERO, NFIX, */
+ /* DELTA (4 bytes for charmm format, 8 bytes for x-plor format), */
+ /* NEXTRA (charmm only), N4DIM, 6*ZERO, NCHARM, 24 */
if (!s_WriteInt32(dr, 84) ||
write(dr->fd, "CORD", 4) != 4 ||
!s_WriteInt32(dr, dr->nframes) ||
!s_WriteInt32(dr, dr->nstart) ||
!s_WriteInt32(dr, dr->ninterval) ||
!s_WriteInt32(dr, dr->nend) ||
- !s_WriteZeros(dr->fd, 20) ||
+ !s_WriteZeros(dr->fd, 16) ||
+ !s_WriteInt32(dr, dr->nfix) ||
!s_WriteSFloat32(dr, dr->delta) ||
- !s_WriteInt32(dr, dr->with_unitcell) ||
+ !s_WriteInt32(dr, dr->nextra) ||
!s_WriteZeros(dr->fd, 32) ||
- !s_WriteInt32(dr, 24) ||
+ !s_WriteInt32(dr, dr->ncharmver) ||
!s_WriteInt32(dr, 84))
return 1; /* Cannot write */
DcdReadFrame(DcdRecord *dr, int index, SFloat32 *xp, SFloat32 *yp, SFloat32 *zp, SFloat32 *cellp)
{
Int32 nn, nnn, i;
- off_t block_size = 24 + (off_t)(dr->natoms * 12) + (dr->with_unitcell ? 56 : 0);
+ off_t block_size = (index > 0 ? dr->block_size : 24 + (off_t)(dr->natoms * 12) + (dr->nextra ? 56 : 0));
lseek(dr->fd, dr->header_size + block_size * index, SEEK_SET);
- if (dr->with_unitcell) {
- if (!s_ReadInt32(dr, &nn) || nn != 48)
- goto error;
- if (cellp != NULL) {
- read(dr->fd, cellp, 48);
- for (i = 0; i < 6; i++)
- s_SwapSFloat32(cellp + i);
+ block_size = 0;
+ if (!s_ReadInt32(dr, &nn))
+ goto error;
+ if (nn == 48) {
+ if (dr->nextra) {
+ SFloat64 mycell[6];
+ if (nn != 48)
+ goto error;
+ read(dr->fd, mycell, 48);
+ if (cellp != NULL) {
+ for (i = 0; i < 6; i++) {
+ if (dr->reverse_endian)
+ s_Swap8((char *)(mycell + i));
+ cellp[i] = mycell[i]; /* double -> float */
+ }
+ }
+ if (!s_ReadInt32(dr, &nn) || nn != 48)
+ goto error;
+ } else {
+ lseek(dr->fd, 52, SEEK_CUR);
}
- if (!s_ReadInt32(dr, &nn) || nn != 48)
- goto error;
- }
- if (!s_ReadInt32(dr, &nn) || nn != dr->natoms * 4 ||
+ if (!s_ReadInt32(dr, &nn))
+ goto error;
+ block_size = 56;
+ }
+ if (nn != dr->natoms * 4 ||
read(dr->fd, xp, nn) < nn ||
!s_ReadInt32(dr, &nnn) || nn != nnn)
goto error;
for (i = 0; i < dr->natoms; i++)
s_SwapSFloat32(zp + i);
}
+ block_size += 24 + (off_t)(dr->natoms * 12);
+ if (index == 0)
+ dr->block_size = block_size;
return 0;
error:
return 1;
DcdWriteFrame(DcdRecord *dr, int index, const SFloat32 *xp, const SFloat32 *yp, const SFloat32 *zp, const SFloat32 *cellp)
{
Int32 i;
- if (dr->with_unitcell) {
+ if (dr->nextra) {
if (!s_WriteInt32(dr, 48))
goto error;
for (i = 0; i < 6; i++)
- s_WriteSFloat32(dr, (cellp != NULL ? cellp[i] : 0.0));
+ s_WriteSFloat64(dr, (cellp != NULL ? cellp[i] : 0.0));
if (!s_WriteInt32(dr, 48))
goto error;
}
{
DcdRecord dcd;
SFloat32 *xp, *yp, *zp;
- Vector *vp;
+ Vector *vp, *cp;
IntGroup *ig;
int n;
errbuf[0] = 0;
}
vp = (Vector *)calloc(sizeof(Vector), mp->natoms * dcd.nframes);
+ if (dcd.nextra)
+ cp = (Vector *)calloc(sizeof(Vector), dcd.nframes * 4);
+ else cp = NULL;
xp = (SFloat32 *)malloc(sizeof(SFloat32) * dcd.natoms);
yp = (SFloat32 *)malloc(sizeof(SFloat32) * dcd.natoms);
zp = (SFloat32 *)malloc(sizeof(SFloat32) * dcd.natoms);
if (vp == NULL || xp == NULL || yp == NULL || zp == NULL || ig == NULL) {
snprintf(errbuf, errbufsize, "Cannot allocate memory");
if (vp) free(vp);
+ if (cp) free(cp);
if (xp) free(xp);
if (yp) free(yp);
if (zp) free(zp);
for (n = 0; n < dcd.nframes; n++) {
int i;
Vector *vpp;
- if (DcdReadFrame(&dcd, n, xp, yp, zp, dcd.globalcell)) {
+ SFloat32 dcdcell[6];
+ if (DcdReadFrame(&dcd, n, xp, yp, zp, dcdcell)) {
snprintf(errbuf, errbufsize, "Read error in dcd file");
goto exit;
}
vpp->y = yp[i];
vpp->z = zp[i];
}
- }
- /* TODO: implement frame-specific cells */
- if (MoleculeInsertFrames(mp, ig, vp, NULL) < 0)
+ if (cp != NULL) {
+ Double sing;
+ vpp = &cp[n * 4];
+ /* dcdcell = {a, gamma, b, beta, alpha, c} */
+ /* angles are described either in cosines (Charmm and NAMD > 2.5) or degrees (NAMD 2.5) */
+ if (dcdcell[1] < -1.0 || dcdcell[1] > 1.0 || dcdcell[3] < -1.0 || dcdcell[3] > 1.0 || dcdcell[4] < -1.0 || dcdcell[4] > 1.0) {
+ dcdcell[4] = cos(dcdcell[4] * kDeg2Rad); /* cos(alpha) */
+ dcdcell[3] = cos(dcdcell[3] * kDeg2Rad); /* cos(beta) */
+ dcdcell[1] = cos(dcdcell[1] * kDeg2Rad); /* cos(gamma) */
+ }
+ /* a axis lies along the cartesian x axis */
+ sing = sqrt(1 - dcdcell[1] * dcdcell[1]);
+ vpp[0].x = dcdcell[0];
+ vpp[0].y = 0;
+ vpp[0].z = 0;
+ vpp[1].x = dcdcell[2] * dcdcell[1];
+ vpp[1].y = dcdcell[2] * sing;
+ vpp[1].z = 0;
+ vpp[2].x = dcdcell[5] * dcdcell[3];
+ vpp[2].y = dcdcell[5] * (dcdcell[4] - dcdcell[3] * dcdcell[1]) / sing;
+ vpp[2].z = sqrt(dcdcell[5] * dcdcell[5] - vpp[2].x * vpp[2].x - vpp[2].y * vpp[2].y);
+ vpp[3].x = vpp[3].y = vpp[3].z = 0.0;
+ if (mp->cell == NULL) {
+ /* Create periodicity if not present */
+ static const char pflags[] = {1, 1, 1};
+ MoleculeSetPeriodicBox(mp, &vpp[0], &vpp[1], &vpp[2], &vpp[3], pflags);
+ }
+ }
+ }
+ if (MoleculeInsertFrames(mp, ig, vp, cp) < 0)
snprintf(errbuf, errbufsize, "Cannot insert frames");
- if (dcd.with_unitcell) {
- Vector ax, ay, az, orig;
- char flags[3] = {1, 1, 1};
- ax.x = dcd.globalcell[0]; ax.y = ax.z = 0;
- ay.y = dcd.globalcell[1]; ay.x = ay.z = 0;
- az.z = dcd.globalcell[2]; az.x = az.y = 0;
- orig.x = dcd.globalcell[3];
- orig.y = dcd.globalcell[4];
- orig.z = dcd.globalcell[5];
- if (MoleculeSetPeriodicBox(mp, &ax, &ay, &az, &orig, flags) != 0) {
- snprintf(errbuf, errbufsize, "Cannot set unit cell");
- goto exit;
- }
- }
mp->startStep = dcd.nstart;
mp->stepsPerFrame = dcd.ninterval;
mp->psPerStep = dcd.delta;
exit:
DcdClose(&dcd);
+ if (cp != NULL)
+ free(cp);
free(vp);
free(xp);
free(yp);
if (dcd.ninterval == 0)
dcd.ninterval = 1;
dcd.nend = dcd.nstart + (dcd.nframes - 1) * dcd.ninterval;
- if (mp->cell != NULL) {
- dcd.with_unitcell = 1;
- dcd.globalcell[0] = VecLength(mp->cell->axes[0]);
- dcd.globalcell[1] = VecLength(mp->cell->axes[1]);
- dcd.globalcell[2] = VecLength(mp->cell->axes[2]);
- dcd.globalcell[3] = mp->cell->origin.x;
- dcd.globalcell[4] = mp->cell->origin.y;
- dcd.globalcell[5] = mp->cell->origin.z;
- }
+ if (mp->cell != NULL)
+ dcd.nextra = 1;
dcd.delta = mp->psPerStep;
if (dcd.delta == 0.0)
dcd.delta = 1.0;
+ dcd.ncharmver = 24;
n = DcdCreate(fname, &dcd);
if (n != 0) {
if (n < 0)
memset(yp + i, 0, sz);
memset(zp + i, 0, sz);
}
+ if (n < mp->nframes && mp->frame_cells != NULL) {
+ Vector *cp = &(mp->frame_cells[n * 4]);
+ dcd.globalcell[0] = VecLength(cp[0]);
+ dcd.globalcell[2] = VecLength(cp[1]);
+ dcd.globalcell[5] = VecLength(cp[2]);
+ dcd.globalcell[1] = VecDot(cp[0], cp[1]) / (dcd.globalcell[0] * dcd.globalcell[2]);
+ dcd.globalcell[3] = VecDot(cp[0], cp[2]) / (dcd.globalcell[0] * dcd.globalcell[5]);
+ dcd.globalcell[4] = VecDot(cp[1], cp[2]) / (dcd.globalcell[2] * dcd.globalcell[5]);
+ }
if (DcdWriteFrame(&dcd, n, xp, yp, zp, dcd.globalcell)) {
snprintf(errbuf, errbufsize, "Write error in dcd file");
goto exit;
}
/* Insert Import-only file types before "All files" */
wildcard += _T("|AMBER mdcrd file (*.crd;*.mdcrd)|*.crd;*.mdcrd");
+ wildcard += _T("|DCD file (*.dcd)|*.dcd");
if (i == -1)
wildcard += (_T("|") + desc + _T(" (") + filter + _T(")|") + filter);
}
MyDocument::OnExport(wxCommandEvent& event)
{
wxString wildcard;
+ wxFileName fname(GetFilename());
+ wxString fnstr;
+ GetPrintableName(fnstr);
{
/* File filter is built from MyDocManager information */
wxString desc, filter, ext;
int i;
MyDocManager *docm = wxGetApp().DocManager();
+ if ((i = fnstr.Find('.', true)) != wxNOT_FOUND) {
+ fnstr = fnstr.Mid(0, i);
+ }
for (i = 0; docm->GetDocumentDescriptionAtIndex(i, &desc, &filter, &ext); i++) {
- if (ext == _T("out") || ext == _T("log") || ext == _T("fchk"))
+ if (ext == _T("mbsf") || ext == _T("out") || ext == _T("log") || ext == _T("fchk"))
continue;
+ if (filter.Contains(_T("*.*"))) {
+ i = -1;
+ break;
+ }
if (wildcard != _T("")) {
wildcard += (_T("|"));
}
wildcard += (desc + _T(" (") + filter + _T(")|") + filter);
}
+ wildcard += _T("|AMBER mdcrd file (*.crd;*.mdcrd)|*.crd;*.mdcrd");
+ wildcard += _T("|DCD file (*.dcd)|*.dcd");
+ if (i == -1)
+ wildcard += (_T("|") + desc + _T(" (") + filter + _T(")|") + filter);
}
-
- wxFileDialog *dialog = new wxFileDialog(NULL, _T(""), _T(""), _T(""), wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxFD_CHANGE_DIR);
+ wxFileDialog *dialog = new wxFileDialog(NULL, _T("Export coordinates"), fname.GetPath(), fnstr + _T(".psf"), wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxFD_CHANGE_DIR);
if (dialog->ShowModal() == wxID_OK) {
char *p = strdup((const char *)(dialog->GetPath().mb_str(wxConvFile)));
MoleculeLock(mol);