diff --git a/CMakeLists.txt b/CMakeLists.txt index daaaee0b8a..f3577f4061 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,9 +3,9 @@ project(cpptraj NONE) #version number #--------------------------------------------------------------------------------------------------------------------------------------------------------------------- -set(cpptraj_MAJOR_VERSION 4) -set(cpptraj_MINOR_VERSION 3) -set(cpptraj_TWEAK_VERSION 4) +set(cpptraj_MAJOR_VERSION 6) +set(cpptraj_MINOR_VERSION 0) +set(cpptraj_TWEAK_VERSION 0) set(cpptraj_VERSION "${cpptraj_MAJOR_VERSION}.${cpptraj_MINOR_VERSION}.${cpptraj_TWEAK_VERSION}") @@ -49,10 +49,12 @@ if(NOT INSIDE_AMBER) set(BUNDLE_SIGNATURE CPTJ) include(Packaging) - # header installation option + # build options option(INSTALL_HEADERS "Copy headers to the include/cpptraj folder of the install directory. Useful for building with pytraj." FALSE) option(BUILD_PARALLEL_COMBINATIONS "If true, then combinations of all enabled parallelizations will be built, e.g. cpptraj.OMP.MPI and cpptraj.OMP.MPI.cuda" FALSE) + + option(INSTALL_TESTS "Copy tests to the test/ folder of the install directory" FALSE) else() set(INSTALL_HEADERS FALSE) set(BUILD_PARALLEL_COMBINATIONS FALSE) @@ -67,4 +69,4 @@ add_subdirectory(test) #-------------------------------------------------------------- if(NOT INSIDE_AMBER) print_build_report() -endif() \ No newline at end of file +endif() diff --git a/devtools/CheckForMissingSource.sh b/devtools/CheckForMissingSource.sh new file mode 100755 index 0000000000..805b8e6a57 --- /dev/null +++ b/devtools/CheckForMissingSource.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +MAKE_SOURCES=`ls *files` +if [ -z "$MAKE_SOURCES" ] ; then + MAKE_SOURCES=Makefile +fi +CMAKE_SOURCES=CMakeLists.txt + +echo "Make sources : $MAKE_SOURCES" +echo "Cmake sources : $CMAKE_SOURCES" + +if [ ! -f "$MAKE_SOURCES" ] ; then + echo "Make sources not found." + exit 1 +fi + +if [ ! -f "$CMAKE_SOURCES" ] ; then + echo "Cmake sources not found." + exit 1 +fi + +SOURCES=`ls *.cpp *.c *.F90 2> /dev/null` + +for FILE1 in $MAKE_SOURCES $CMAKE_SOURCES ; do + for FILE2 in $SOURCES ; do + if [ -z "`grep $FILE2 $FILE1`" ] ; then + echo "$FILE2 appears to be missing from $FILE1" + fi + done +done diff --git a/devtools/RunCmake.sh b/devtools/RunCmake.sh new file mode 100755 index 0000000000..97d00b4ca2 --- /dev/null +++ b/devtools/RunCmake.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Can be used to test the cmake install. +# Assumes 'git submodule update --init --recursive' has been run in top dir. + +if [ -z "$CPPTRAJHOME" ] ; then + echo "CPPTRAJHOME must be set." + exit 1 +fi +HOME=$CPPTRAJHOME + +installdir=$HOME/install +if [ ! -d "$installdir" ] ; then + mkdir $installdir +fi + +#export BUILD_FLAGS="-DOPENMP=TRUE" +#export BUILD_FLAGS="-DMPI=TRUE ${BUILD_FLAGS}" +#-DNetCDF_LIBRARIES_C=$HOME/lib/libnetcdf.so -DNetCDF_INCLUDES=$HOME/include +COMPILER=gnu +cmake .. $BUILD_FLAGS -DCOMPILER=${COMPILER^^} -DINSTALL_HEADERS=FALSE \ + -DCMAKE_INSTALL_PREFIX=$installdir -DCMAKE_LIBRARY_PATH=$HOME/lib \ + -DPRINT_PACKAGING_REPORT=TRUE + diff --git a/doc/cpptraj.lyx b/doc/cpptraj.lyx index d367e77aec..820f2b9c4e 100644 --- a/doc/cpptraj.lyx +++ b/doc/cpptraj.lyx @@ -2791,7 +2791,7 @@ status open \begin_layout Plain Layout \align center \begin_inset Tabular - + @@ -3514,7 +3514,7 @@ Read Only - + \begin_inset Text \begin_layout Plain Layout @@ -3523,7 +3523,7 @@ Charmm Output \end_inset - + \begin_inset Text \begin_layout Plain Layout @@ -3532,7 +3532,7 @@ Charmm Output \end_inset - + \begin_inset Text \begin_layout Plain Layout @@ -3541,7 +3541,7 @@ charmmout \end_inset - + \begin_inset Text \begin_layout Plain Layout @@ -3550,13 +3550,107 @@ charmmout \end_inset - + \begin_inset Text \begin_layout Plain Layout Energy information, Read Only \end_layout +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Pairwise Cache (binary) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +.cmatrix +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +cmatrix +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +pairwise distances +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Used for cluster analysis. +\end_layout + +\end_inset + + + + +\begin_inset Text + +\begin_layout Plain Layout +Pairwise Cache (NetCDF) +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +.nccmatrix +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +nccmatrix +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +pairwise distances +\end_layout + +\end_inset + + +\begin_inset Text + +\begin_layout Plain Layout +Used for cluster analysis. +\end_layout + \end_inset @@ -5148,6 +5242,20 @@ Cpptraj if this is not successful. \end_layout +\begin_layout Standard +If a file contains the header: +\end_layout + +\begin_layout LyX-Code +#F1 F2 +\end_layout + +\begin_layout Standard +CPPTRAJ will assume the file contains pairwise distances for clustering, + where the F1 and F2 columns contain the frame numbers, and the column + contains the distance. +\end_layout + \begin_layout Subsection Grace Data File Options \end_layout @@ -40100,11 +40208,24 @@ cluster \end_inset - [crdset | nocoords] + [crdset ] [data [,...]] [nocoords] \end_layout \begin_layout LyX-Code - Algorithms: + [] [] [] [] [] [] +\end_layout + +\begin_layout LyX-Code + [] [] [] +\end_layout + +\begin_layout LyX-Code + [readinfo {infofile | cnvtset }] +\end_layout + +\begin_layout LyX-Code + Algorithm Args: [{hieragglo|dbscan|kmeans|dpeaks}] \end_layout \begin_layout LyX-Code @@ -40112,64 +40233,79 @@ cluster \end_layout \begin_layout LyX-Code - [epsilonplot ] [includesieved_cdist]] + [epsilonplot ]] \end_layout \begin_layout LyX-Code - [dbscan minpoints epsilon [sievetoframe] [kdist [kfile ]]] + [dbscan minpoints epsilon [kdist [kfile ]]] \end_layout \begin_layout LyX-Code - [dpeaks epsilon [noise] [dvdfile ] + [kmeans clusters [randompoint [kseed ]] [maxit ]] \end_layout \begin_layout LyX-Code - [choosepoints {manual | auto}] + [dpeaks epsilon [noise] [dvdfile ] \end_layout \begin_layout LyX-Code - [distancecut ] [densitycut ] + [choosepoints {manual | auto}] \end_layout \begin_layout LyX-Code - [runavg ] [deltafile ] [gauss]] + [distancecut ] [densitycut ] \end_layout \begin_layout LyX-Code - [kmeans clusters [randompoint [kseed ]] [maxit ] + [runavg ] [deltafile ] [gauss]] \end_layout \begin_layout LyX-Code - [{readtxt|readinfo} infofile ] + Metric Args: \end_layout \begin_layout LyX-Code - Distance options: + [{dme|rms|srmsd} [mass] [nofit] []] [{euclid|manhattan}] [wgt ] \end_layout \begin_layout LyX-Code - {[[rms | srmsd] [] [mass] [nofit]] | [dme []] | + Pairwise Args: \end_layout \begin_layout LyX-Code - [data [,,...]]} + [pairdist ] [pwrecalc] \end_layout \begin_layout LyX-Code - [sieve <#> [random [sieveseed <#>]]] [loadpairdist] [savepairdist] [pairdist - ] + [loadpairdist] [savepairdist] [pairwisecache {mem|disk|none}] +\end_layout + +\begin_layout LyX-Code + Sieve Args: +\end_layout + +\begin_layout LyX-Code + [sieve <#> [sieveseed <#>] [random] [includesieveincalc] [includesieved_cdist] +\end_layout + +\begin_layout LyX-Code + [{sievetoframe|sievetocentroid|closestcentroid}] [repsilon ]] \end_layout \begin_layout LyX-Code - [pairwisecache {mem | none}] [includesieveincalc] [pwrecalc] + BestRep Args: \end_layout \begin_layout LyX-Code - Output options: + [bestrep {cumulative|centroid|cumulative_nosieve}] [savenreps <#>] \end_layout \begin_layout LyX-Code - [out ] [gracecolor] [summary ] [info ] + Output Args: +\end_layout + +\begin_layout LyX-Code + [out [gracecolor]] [noinfo|info ] [summary ] \end_layout \begin_layout LyX-Code @@ -40177,39 +40313,43 @@ cluster \end_layout \begin_layout LyX-Code - [bestrep {cumulative|centroid|cumulative_nosieve}] [savenreps <#>] + [clustersvtime [cvtwindow <#>]] [sil ] [metricstats ] \end_layout \begin_layout LyX-Code - [clustersvtime cvtwindow ] + [cpopvtime [{normpop|normframe}]] [lifetime] \end_layout \begin_layout LyX-Code - [cpopvtime [normpop | normframe] [lifetime]] + Coordinate Output Args: \end_layout \begin_layout LyX-Code - [sil ] [assignrefs [refcut ] [refmask ]] + [clusterout [clusterfmt ]] \end_layout \begin_layout LyX-Code - Coordinate output options: + [singlerepout [singlerepfmt ]] \end_layout \begin_layout LyX-Code - [ clusterout [clusterfmt ] ] + [repout [repfmt ] [repframe]] \end_layout \begin_layout LyX-Code - [ singlerepout [singlerepfmt ] ] + [avgout [avgfmt ]] \end_layout \begin_layout LyX-Code - [ repout [repfmt ] [repframe] ] + [assignrefs [refcut ] [refmask ]] \end_layout \begin_layout LyX-Code - [ avgout [avgfmt ] ] + Graph Args: +\end_layout + +\begin_layout LyX-Code + [{drawgraph|drawgraph3d} [draw_tol ] [draw_maxit ] Name of previously generated COORDS data set. - If not specified the default COORDS set will be used unless +set>] Name of COORDS data set to cluster on and/or use for coordinate output. + If not specified the default COORDS set will be generated and used unless + \series bold nocoords \series default has been specified. \end_layout +\begin_layout Description +[data +\begin_inset space ~ +\end_inset + +[,,...] Distance between frames calculated using specified data + set(s). + Currently 1D scalar sets and COORDS sets are supported. +\end_layout + +\begin_deeper \begin_layout Description [nocoords] Do not use a COORDS data set; distance metrics that require coordinat -es and coordiante output will be disabled. +es and coordinate output will be disabled. \end_layout +\end_deeper +\begin_layout Description +[] Data set Name for generated cluster data sets. +\end_layout + +\begin_layout Description +[readinfo] Use previous cluster results to set up initial clusters. + Clustering will continue if possible (i.e. + this can be used to restart clustering). +\begin_inset Separator latexpar +\end_inset + + +\end_layout + +\begin_deeper +\begin_layout Description +infofile +\begin_inset space ~ +\end_inset + + Cluster +\series bold +info +\series default + file to read clusters from. +\end_layout + +\begin_layout Description +cnvtset +\begin_inset space ~ +\end_inset + + Cluster number vs time data set to use to generate initial clusters. +\end_layout + +\end_deeper \begin_layout Standard Algorithms: \end_layout @@ -40314,15 +40503,6 @@ averagelinkage] . \end_layout -\begin_layout Description -[includesieved_cdist] Include sieved frames in final cluster distance calculatio -n ( -\bar under -may be very slow -\bar default -). -\end_layout - \end_deeper \begin_layout Description dbscan Use DBSCAN clustering algorithm of Ester et al. @@ -40357,11 +40537,6 @@ epsilon Distance cutoff between points for forming a cluster. \end_layout -\begin_layout Description -[sievetoframe] When restoring sieved frames, compare frame to every frame - in a cluster instead of the centroid; slower but more accurate. -\end_layout - \begin_layout Description [kdist \begin_inset space ~ @@ -40568,31 +40743,13 @@ randompoint iterations are reached (default 100). \end_layout -\end_deeper -\begin_layout Description -readtxt|readinfo No clustering - read in previous cluster results. -\begin_inset Separator latexpar -\end_inset - - -\end_layout - -\begin_deeper -\begin_layout Description -infofile -\begin_inset space ~ -\end_inset - - Cluster info file to read. -\end_layout - \end_deeper \begin_layout Standard Distance Metric Options: \end_layout \begin_layout Description -[rms +[{rms \begin_inset space ~ \end_inset @@ -40600,12 +40757,16 @@ Distance Metric Options: \begin_inset space ~ \end_inset -srmsd[]] (Default +srmsd} +\begin_inset space ~ +\end_inset + +[]] (Default \series bold rms \series default -) Distance between frames calculated via best-fit coordinate RMSD using - atoms in +) For COORDS data, distance between coordinate frames calculated via best-fit + coordinate RMSD using atoms in \series bold \series default @@ -40643,8 +40804,8 @@ dme \begin_inset space ~ \end_inset -[] Distance between frames calculated using distance-RMSD (aka DME, - +[] For COORDS data, distance between coordinate frames calculated + using distance-RMSD (aka DME, \series bold \emph on distrmsd @@ -40658,12 +40819,106 @@ distrmsd \end_layout \begin_layout Description -[data +euclid Use Euclidean distance (sqrt(SUM(distance^2))) when more than one + data set has been specified (default). +\end_layout + +\begin_layout Description +manhatttan Use Manhattan distance (SUM(distance)) when more than one data + set has been specified. +\end_layout + +\begin_layout Description +wgt \begin_inset space ~ \end_inset -[,,...] Distance between frames calculated using specified data - set(s) (Euclidean distance). + Factor to multiply distances from each metric by in a comma-separated + list. + Can be used to adjust the contribution from each metric. + Default is 1 for each metric. + Output from the +\series bold +metricstats +\series default + keyword can be used to determine the relative contribution of each metric + to the distance. +\end_layout + +\begin_layout Standard +Pairwise Distance Matrix Options: +\end_layout + +\begin_layout Description +[pairdist +\begin_inset space ~ +\end_inset + +] Pairwise cache DataSet/File name to use for loading/saving pairwise + distances. +\end_layout + +\begin_layout Description +[pwrecalc] If the loaded pairwise distance matrix does not match the current + setup, force recalculation. +\end_layout + +\begin_layout Description +[loadpairdist] Load pairwise distances from file specified by +\series bold +pairdist +\series default + (CpptrajPairDist if +\series bold +pairdist +\series default + not specified). +\end_layout + +\begin_layout Description +[savepairdist] Save pairwise distances to file specified by +\series bold +pairdist +\series default + (CpptrajPairDist if +\series bold +pairdist +\series default + not specified). + NOTE: If sieving was performed only the calculated distances are saved. +\end_layout + +\begin_layout Description +[pairwisecache +\begin_inset space ~ +\end_inset + +{mem +\begin_inset space ~ +\end_inset + +| +\begin_inset space ~ +\end_inset + +disk +\begin_inset space ~ +\end_inset + +| +\begin_inset space ~ +\end_inset + +none}] Cache pairwise distance data in memory (default), to disk, or disable + pairwise caching. + No caching will save memory but be extremely slow. + Caching to disk will likely be slow unless writing to a fast storage device + (e.g. + SSD) - data is saved to a file named 'CpptrajPairwiseCache'. +\end_layout + +\begin_layout Standard +Sieving Options: \end_layout \begin_layout Description @@ -40696,71 +40951,109 @@ sieve \end_layout \begin_layout Description -[pairdist -\begin_inset space ~ -\end_inset +[includesieved_cdist] Include sieved frames in final cluster distance calculatio +n ( +\bar under +may be very slow +\bar default +). +\end_layout -] File to use for loading/saving pairwise distances. +\begin_layout Description +[includesieveincalc] Include sieved frames when calculating within-cluster + average ( +\bar under +may be very slow +\bar default +). \end_layout \begin_layout Description -[loadpairdist] Load pairwise distances from +[sievetoframe] When restoring sieved frames, compare frame to every frame + in a cluster using a cutoff of \series bold - + \series default - (CpptrajPairDist if pairdist not specified). + (default is algorithm +\series bold +epsilon +\series default + when using DPeaks/DBscan) instead of the centroid; slower but more accurate. \end_layout \begin_layout Description -[savepairdist] Save pairwise distances from +[sievetocentroid] When restoring sieved frames, compare frame to cluster + centroid using a cutoff of \series bold - + \series default - (CpptrajPairDist if pairdist not specified). - NOTE: If sieving was performed only the calculated distances are saved. + (default is algorithm +\series bold +epsilon +\series default + when using DPeaks/DBscan). + Default method for DPeaks/DBSCAN. \end_layout \begin_layout Description -[pairwisecache -\begin_inset space ~ -\end_inset +[closestcentroid] When restoring sieved frames, add each frame to its closest + centroid. + Default method for hieragglo/kmeans. +\end_layout -{mem +\begin_layout Description +[repsilon \begin_inset space ~ \end_inset -| +] Epsilon to use for sievetoframe/sievetocentroid (default is algorithm + +\series bold +epsilon +\series default + when using DPeaks/DBscan). +\end_layout -| +\begin_layout Standard +Best Representative Options: +\end_layout + +\begin_layout Description +[bestrep \begin_inset space ~ \end_inset -none}] Cache pairwise distance data in memory (default), to disk, or disable - pairwise caching. - No caching will save memory but be extremely slow. - Caching to disk will likely be slow unless writing to a fast storage device - (e.g. - SSD) - data is saved to a file named 'CpptrajPairwiseCache'. +{cumulative|centroid|cumulative_nosieve}] Method for choosing cluster representa +tive frames. \end_layout +\begin_deeper \begin_layout Description -[includesieveincalc] Include sieved frames when calculating within-cluster - average ( -\bar under -may be very slow -\bar default -). +cumulative Choose by lowest cumulative distance to all other frames in cluster. + Default when not sieving. \end_layout \begin_layout Description -[pwrecalc] If a loaded pairwise distance file does not match the current - setup, force recalculation. +centroid Choose by lowest distance to cluster centroid. + Default when sieving. +\end_layout + +\begin_layout Description +cumulative_nosieve Choose by lowest cumulative distance to all other frames, + ignoring sieved frames. +\end_layout + +\end_deeper +\begin_layout Description +[savenreps +\begin_inset space ~ +\end_inset + +<#>] Number of best representative frames to choose (default 1). \end_layout \begin_layout Standard @@ -40781,6 +41074,7 @@ Output Options: DBSCAN) will assign noise points a value of -1. \end_layout +\begin_deeper \begin_layout Description [gracecolor] Instead of cluster # vs frame, write cluster# + 1 (corresponding to colors used by XMGRACE) vs frame. @@ -40789,6 +41083,7 @@ Output Options: DBSCAN) will assign noise points a color of 0 (blank). \end_layout +\end_deeper \begin_layout Description [summary \begin_inset space ~ @@ -40826,6 +41121,9 @@ Stdev Standard deviation of points in the cluster. \begin_layout Description Centroid Frame # of structure in cluster that has the lowest cumulative distance to every other point. + If multiple representatives are being saved this column is replaced with + two columns for each representative, 'Rep' (representative frame #) and + 'RepScore' (score according to current best representative metric). \end_layout \begin_layout Description @@ -40867,6 +41165,10 @@ AvgCDist Average distance of this cluster to every other cluster. \begin_inset Newline newline \end_inset +#SSR/SST: +\begin_inset Newline newline +\end_inset + #Algorithm: \begin_inset Newline newline \end_inset @@ -40886,13 +41188,17 @@ AvgCDist Average distance of this cluster to every other cluster. Where is the number of clusters, is the number of frames clustered, ranges from 0 to -1, is the average distance of all frames in that cluster to the centroid, is the Davies-Bouldin Index, - is the pseudo-F statistic, and contains the - frame # of the representative frame (i.e. + is the pseudo-F statistic, is the SSR/SST ratio, and contains the frame # of the representative frame (i.e. closest to the centroid) for each cluster. Each cluster has a line made up of characters (one for each frame) where '.' means 'not in cluster' and 'X' means 'in cluster'. \end_layout +\begin_layout Description +[noinfo] Suppress printing of cluster info. +\end_layout + \begin_layout Description [summarysplit \begin_inset space ~ @@ -40902,7 +41208,8 @@ Where is the number of clusters, is the number of frames clustered, portions of the trajectory specified by splitframe with format '#Cluster Total Frac C# Color NumInX ... FracX ... - FirstX': + FirstX ... + RepX': \begin_inset Separator latexpar \end_inset @@ -40943,6 +41250,11 @@ FirstX Frame in the Xth portion of the trajectory where the cluster is first observed. \end_layout +\begin_layout Description +RepX Best representative frame in the Xth portion of the trajectory for + that cluster. +\end_layout + \end_deeper \begin_layout Description [splitframe @@ -40958,58 +41270,66 @@ summarysplit \end_layout \begin_layout Description -[bestrep +[clustersvtime \begin_inset space ~ \end_inset -{cumulative|centroid|cumulative_nosieve}] Method for choosing cluster representa -tive frames. +] Write number of unique clusters observed in a given time window + to . \end_layout \begin_deeper \begin_layout Description -cumulative Choose by lowest cumulative distance to all other frames in cluster. - Default when not sieving. -\end_layout - -\begin_layout Description -centroid Choose by lowest distance to cluster centroid. - Default when sieving. -\end_layout - -\begin_layout Description -cumulative_nosieve Choose by lowest cumulative distance to all other frames, - ignoring sieved frames. -\end_layout - -\end_deeper -\begin_layout Description -[savenreps +[cvtwindow \begin_inset space ~ \end_inset -<#>] Number of best representative frames to choose (default 1). +] Window size for +\series bold +clustersvtime +\series default + output. \end_layout +\end_deeper \begin_layout Description -[clustersvtime +[sil \begin_inset space ~ \end_inset -] Write number of unique clusters observed in a given time window - to . +] Write average cluster silhouette value for each cluster to '.cl +uster.dat' and cluster silhouette value for each individual frame to '.fra +me.dat'. \end_layout \begin_layout Description -[cvtwindow +[metricstats \begin_inset space ~ \end_inset -] Window size for +] When more than one metric in use, print the fraction contribution + of each metric to the total distance. + This information can be used in conjunction with the \series bold -clustersvtime +wgt \series default - output. + keyword to adjust the contribution of each metric to the total distance. + It is written to with format: +\begin_inset Newline newline +\end_inset + +#Metric FracAv FracSD Avg SD Min Max Description +\begin_inset Newline newline +\end_inset + +Where #Metric is the metric number, FracAv and FracSD are the average and + standard devation of the fraction contribution of that metric to the total + distance (taking into account distance type and weights), Avg, SD, Min, + and Max are the average, standard devation, minimum, and maximum of the + unmodified distance contribution from that metric, and Description is the + metric description. + This may be slow for large numbers of frames, so it is advisable to run + this on a smaller (potentially sieved) number of frames. \end_layout \begin_layout Description @@ -41045,47 +41365,31 @@ normframe \end_layout \begin_layout Description -[sil -\begin_inset space ~ -\end_inset - -] Write average cluster silhouette value for each cluster to '.cl -uster.dat' and cluster silhouette value for each individual frame to '.fra -me.dat'. -\end_layout - -\begin_layout Description -assignrefs In -\series bold -summary -\series default -/ +[lifetime] Create a DataSet with aspect +\emph on +[Lifetime] +\emph default + for each cluster; for each frame, have 1 if the cluster is present and + 0 otherwise. + Can be used with \series bold -summarysplit +\emph on +lifetime \series default -, assign clusters to loaded representative structures if RMSD to that reference - is less than specified cutoff. -\end_layout - -\begin_deeper -\begin_layout Description -[refcut -\begin_inset space ~ -\end_inset - -] RMSD cutoff in Angstroms. -\end_layout +\emph default + analysis ( +\begin_inset CommandInset ref +LatexCommand vref +reference "subsec:cpptraj-lifetime" +plural "false" +caps "false" +noprefix "false" -\begin_layout Description -[refmask -\begin_inset space ~ \end_inset -] Mask to use for RMSD calculation. - If not specified the default mask is all heavy atoms. +). \end_layout -\end_deeper \begin_layout Standard Coordinate Output Options: \end_layout @@ -41099,6 +41403,7 @@ clusterout where X is the cluster number. \end_layout +\begin_deeper \begin_layout Description clusterfmt \begin_inset space ~ @@ -41107,6 +41412,7 @@ clusterfmt Format keyword for clusterout (default Amber Trajectory). \end_layout +\end_deeper \begin_layout Description singlerepout \begin_inset space ~ @@ -41116,6 +41422,7 @@ singlerepout . \end_layout +\begin_deeper \begin_layout Description singlerepfmt \begin_inset space ~ @@ -41124,6 +41431,7 @@ singlerepfmt Format keyword for singlerepout (default Amber Trajectory). \end_layout +\end_deeper \begin_layout Description repout \begin_inset space ~ @@ -41134,6 +41442,7 @@ repout extension. \end_layout +\begin_deeper \begin_layout Description repfmt \begin_inset space ~ @@ -41150,6 +41459,7 @@ repout filename. \end_layout +\end_deeper \begin_layout Description avgout \begin_inset space ~ @@ -41160,6 +41470,7 @@ avgout filename extension. \end_layout +\begin_deeper \begin_layout Description avgfmt \begin_inset space ~ @@ -41168,12 +41479,82 @@ avgfmt Format keyword for avgout. \end_layout +\end_deeper +\begin_layout Description +assignrefs In +\series bold +summary +\series default +/ +\series bold +summarysplit +\series default +, assign clusters to loaded reference structures if RMSD to that reference + is less than specified cutoff. + This will be printed in +\series bold +summary +\series default + and +\series bold +summarysplit +\series default + files as 2 extra columns: 'Name' (reference name) and 'RMS' (RMS to cluster + centroid). +\end_layout + +\begin_deeper +\begin_layout Description +[refcut +\begin_inset space ~ +\end_inset + +] RMSD cutoff in Angstroms. +\end_layout + +\begin_layout Description +[refmask +\begin_inset space ~ +\end_inset + +] Mask to use for RMSD calculation. + If not specified the default mask is all heavy atoms. +\end_layout + +\end_deeper \begin_layout Standard -DataSet Aspects: +DataSets Created: +\end_layout + +\begin_layout Description + Cluster number vs time (color number if +\series bold +gracecolor +\series default + specified). +\end_layout + +\begin_layout Description +[NCVT] ( +\series bold +clustersvtime +\series default + only). + Number of unique clusters observed over time. \end_layout \begin_layout Description -[Pop] Cluster population vs time; index corresponds to cluster number. +[Pop]: Cluster X population vs time; index X corresponds to cluster + number. +\end_layout + +\begin_layout Description +[Lifetime]: ( +\series bold +lifetime +\series default + only). + For each cluster X, contain 1 if cluster present that frame, 0 otherwise. \end_layout \end_deeper @@ -41185,9 +41566,17 @@ Note cluster population vs time data sets are not generated until the analysis \end_layout \begin_layout Standard -Cluster input frames using the specified clustering algorithm and distance - metric. - In order to speed up clustering of large trajectories, the +Cluster input frames using the specified input data sets (can be any combination + of coordinates/COORDS and/or 1D scalar data) with the specified clustering + algorithm. + For COORDS sets, the distance metric can be RMSD, symmetry-corrected RMSD, + or DME. + When multiple data sets are present, the total distance can be determined + either via the Euclidean (default) or Manhattan method. +\end_layout + +\begin_layout Standard +In order to speed up clustering of large trajectories, the \series bold sieve \series default @@ -41226,9 +41615,11 @@ cluster data endToEnd clusters 10 epsilon 3.0 summary summary.dat info info.dat \end_layout \begin_layout Standard -Example: cluster on the CA atoms of residues 2-10 using average-linkage, - stopping when either 3 clusters are reached or the minimum distance between - clusters is 4.0, writing the cluster number vs time to +Example: two clustering commands on the CA atoms of residues 2-10 using + average-linkage, stopping when either 3 clusters are reached or the minimum + distance between clusters is 4.0 for the first, and 8 clusters or minimum + distance 2.0 for the second. + The first command will write the cluster number vs time to \begin_inset Quotes eld \end_inset @@ -41244,15 +41635,22 @@ avg.summary.dat \begin_inset Quotes erd \end_inset -: +. + The second clustering command will use the pairwise distance matrix from + the first to speed things up: +\end_layout + +\begin_layout LyX-Code +cluster C1 :2-10 clusters 3 epsilon 4.0 info C1.info out cnumvtime.dat summary + avg.summary.dat pairdist PW \end_layout \begin_layout LyX-Code -cluster C1 :2-10 clusters 3 epsilon 4.0 out cnumvtime.dat summary avg.summary.dat +cluster C2 :2-10 clusters 8 epsilon 2.0 info C2.info pairdist PW \end_layout \begin_layout Subsubsection* -Clustering Metrics +Clustering Success Metrics (info file) \end_layout \begin_layout Standard @@ -41276,7 +41674,7 @@ The pseudo-F statistic (pSF) is another measure of clustering goodness. within group. \series bold -High values are good +Higher values of pseudo-F are good \series default . Generally, one selects a cluster-count that gives a peak in the pseudo-f @@ -41288,6 +41686,26 @@ High values are good \end_layout +\begin_layout Standard +The SSR/SST is the ratio of the sum of squares regression (SSR or between + sum of squares) and the total sum of squares (SST). + The SSR is calculated via the sum of the squared distances of all points + within a given cluster to its centroid, and summed together for all clusters. + The total sum of squares is the sum of squared distances for all frames + to the overall mean. + The ratio lies between 0 and 1 and is supposed to give the fraction of + explained variance by the data. + The ratio should increase with cluster count. + +\series bold +There should be a point at which adding more clusters does not substantially + increase SSR/SST +\series default +, i.e. + the point where increasing the cluster count does not add new information + and should not increase further. +\end_layout + \begin_layout Standard The cluster silhouette is a measure of how well each point fits within a cluster. @@ -41386,13 +41804,14 @@ The second way is automatically; cpptraj will attempt to identify outliers \end_layout \begin_layout Subsubsection* -The CpptrajPairDist file format +The Binary pairwise matrix file format \end_layout \begin_layout Standard -The CpptrajPairDist file is binary; the exact format depends on what version - of cpptraj generated the file (since earlier versions had no concept of - 'sieve'). +When NetCDF is not present, the pairwise matrix file will be written in + binary. + The exact format depends on what version of cpptraj generated the file + (since earlier versions had no concept of 'sieve'). The CpptrajPairDist file starts with a 4 byte header containing the characters 'C' 'T' 'M' followed by the version number. A quick way to figure out the version is to use the linux 'od' command @@ -41469,6 +41888,88 @@ The code that cpptraj uses to read in CpptrajPairDist files is in ClusterMatrix: :LoadFile() (ClusterMatrix.cpp). \end_layout +\begin_layout Subsubsection* +The NetCDF pairwise matrix format +\end_layout + +\begin_layout Standard +The default way to write pairwise matrix files as of version 6.0.0 is with + NetCDF. + This will be set up with the following parameters: +\end_layout + +\begin_layout LyX-Code +Attributes: +\end_layout + +\begin_deeper +\begin_layout Description +Conventions +\begin_inset Quotes eld +\end_inset + +CPPTRAJ_CMATRIX +\begin_inset Quotes erd +\end_inset + + +\end_layout + +\begin_layout Description +Version +\end_layout + +\begin_layout Description +MetricDescription +\end_layout + +\end_deeper +\begin_layout LyX-Code +Dimensions: +\end_layout + +\begin_deeper +\begin_layout Description +n_original_frames Number of frames originally in the set (i.e. + before sieving). +\end_layout + +\begin_layout Description +n_rows Number of rows in the upper-triangle pairwise matrix. +\end_layout + +\begin_layout Description +msize Actual size of the matrix; should be (nRows_ * (nRows_-1)) / 2; +\end_layout + +\end_deeper +\begin_layout LyX-Code +Variables: +\end_layout + +\begin_deeper +\begin_layout Description +sieve (integer, no dimension). + Sieve value. +\end_layout + +\begin_layout Description +matrix (float, dimension msize). + The pairwise matrix, flattened to 1 dimension. + Index calc is: i1 = i + 1; index = (((nRows_ * i) - ((i1 * i) / 2)) + j + - i1); +\end_layout + +\begin_layout Description +actual +\begin_inset space ~ +\end_inset + +frames (integer, dimension n_rows). + The actual frame numbers for which pairwise distances were calculated. +\end_layout + +\end_deeper \begin_layout Subsection cphstats \end_layout diff --git a/src/Analysis_Clustering.cpp b/src/Analysis_Clustering.cpp index b47cbef081..e793a3aef1 100644 --- a/src/Analysis_Clustering.cpp +++ b/src/Analysis_Clustering.cpp @@ -1,141 +1,26 @@ -// Analysis_Clustering #include "Analysis_Clustering.h" #include "CpptrajStdio.h" -#include "StringRoutines.h" // fileExists, integerToString -#include "DataSet_integer.h" // For converting cnumvtime -#include "DataSet_float.h" -#include "Trajout_Single.h" -#include "Timer.h" -// Clustering Algorithms -#include "Cluster_HierAgglo.h" -#include "Cluster_DBSCAN.h" -#include "Cluster_Kmeans.h" -#include "Cluster_ReadInfo.h" -#include "Cluster_DPeaks.h" +#include "DataSet_Coords.h" -// CONSTRUCTOR -Analysis_Clustering::Analysis_Clustering() : - masterDSL_(0), - coords_(0), - CList_(0), - sieve_(1), - sieveSeed_(-1), - windowSize_(0), - drawGraph_(0), - draw_maxit_(0), - nRepsToSave_(1), - draw_tol_(0.0), - refCut_(1.0), - cnumvtime_(0), - clustersVtime_(0), - pw_dist_(0), - cpopvtimefile_(0), - pwd_file_(0), - nofitrms_(false), - metric_(ClusterList::RMS), - useMass_(false), - grace_color_(false), - norm_pop_(NONE), - bestRep_(CUMULATIVE), - calc_lifetimes_(false), - writeRepFrameNum_(false), - includeSieveInCalc_(false), - suppressInfo_(false), - pw_mismatch_fatal_(true), - clusterfmt_(TrajectoryFile::UNKNOWN_TRAJ), - singlerepfmt_(TrajectoryFile::UNKNOWN_TRAJ), - reptrajfmt_(TrajectoryFile::UNKNOWN_TRAJ), - avgfmt_(TrajectoryFile::UNKNOWN_TRAJ), - debug_(0) -{ } - -/** The default output trajectory format. */ -const TrajectoryFile::TrajFormatType Analysis_Clustering::DEF_TRAJ_FMT_ = TrajectoryFile::AMBERTRAJ; - -/** The default pairwise distance file name. */ -const char* Analysis_Clustering::PAIRDISTFILE_ = "CpptrajPairDist"; - -/** The default pairwise distance file type. */ -DataFile::DataFormatType Analysis_Clustering::PAIRDISTTYPE_ = -# ifdef BINTRAJ - DataFile::NCCMATRIX; -# else - DataFile::CMATRIX; -# endif - -// DESTRUCTOR -Analysis_Clustering::~Analysis_Clustering() { - if (CList_ != 0) delete CList_; -} +using namespace Cpptraj::Cluster; +// Analysis_Clustering::Help() void Analysis_Clustering::Help() const { - mprintf("\t[crdset | nocoords]\n"); - mprintf(" Algorithms:\n"); - Cluster_HierAgglo::Help(); - Cluster_DBSCAN::Help(); - Cluster_DPeaks::Help(); - Cluster_Kmeans::Help(); - Cluster_ReadInfo::Help(); - mprintf(" Distance metric options: {rms | srmsd | dme | data}\n" - "\t{ [[rms | srmsd] [] [mass] [nofit]] | [dme []] |\n" - "\t [data [,,...]] }\n" - "\t[sieve <#> [random [sieveseed <#>]]] [loadpairdist] [savepairdist] [pairdist ]\n" - "\t[pairwisecache {mem | disk | none}] [includesieveincalc] [pwrecalc]\n" - " Output options:\n" - "\t[out ] [gracecolor] [summary ] [info ]\n" - "\t[summarysplit ] [splitframe ]\n" - "\t[bestrep {cumulative|centroid|cumulative_nosieve}] [savenreps <#>]\n" - "\t[clustersvtime cvtwindow ]\n" - "\t[cpopvtime [normpop | normframe]] [lifetime]\n" - "\t[sil ] [assignrefs [refcut ] [refmask ]]\n" - " Coordinate output options:\n" - "\t[ clusterout [clusterfmt ] ]\n" - "\t[ singlerepout [singlerepfmt ] ]\n" - "\t[ repout [repfmt ] [repframe] ]\n" - "\t[ avgout [avgfmt ] ]\n" - " Experimental options:\n" - "\t[[drawgraph | drawgraph3d] [draw_tol ] [draw_maxit can be created with the 'createcrd' command.\n"); - /// pytraj can turn off cluster info by specifying 'noinfo' keyword -} - -// Analysis_Clustering::GetClusterTrajArgs() -void Analysis_Clustering::GetClusterTrajArgs(ArgList& argIn, - const char* trajKey, const char* fmtKey, - std::string& trajName, - TrajectoryFile::TrajFormatType& fmt) const -{ - trajName = argIn.GetStringKey( trajKey ); - fmt = TrajectoryFile::WriteFormatFromString( argIn.GetStringKey(fmtKey), fmt ); - // If file name specified but not format, try to guess from name - if (!trajName.empty() && fmt == TrajectoryFile::UNKNOWN_TRAJ) - fmt = TrajectoryFile::WriteFormatFromFname( trajName, DEF_TRAJ_FMT_ ); + mprintf("\t[crdset ] [data [,...]] [nocoords]\n"); + Control::Help(); } // Analysis_Clustering::Setup() Analysis::RetType Analysis_Clustering::Setup(ArgList& analyzeArgs, AnalysisSetup& setup, int debugIn) { - debug_ = debugIn; - if (analyzeArgs.hasKey("nocoords")) - coords_ = 0; - else { - // Attempt to get coords dataset from datasetlist - std::string setname = analyzeArgs.GetStringKey("crdset"); - coords_ = (DataSet_Coords*)setup.DSL().FindCoordsSet( setname ); - if (coords_ == 0) { - mprinterr("Error: Could not locate COORDS set corresponding to %s\n", - setname.c_str()); - return Analysis::ERR; - } - } - // Check for DataSet(s) to cluster on, otherwise coords will be used - cluster_dataset_.clear(); + control_.SetDebug( debugIn ); + DataSetList inputDsets; + DataSet_Coords* coords = 0; + // First check for data std::string dataSetname = analyzeArgs.GetStringKey("data"); - metric_ = ClusterList::RMS; if (!dataSetname.empty()) { + // Get data sets for clustering ArgList dsnames(dataSetname, ","); - DataSetList inputDsets; for (ArgList::const_iterator name = dsnames.begin(); name != dsnames.end(); ++name) { DataSetList tempDSL = setup.DSL().GetMultipleSets( *name ); if (tempDSL.empty()) { @@ -144,1027 +29,47 @@ Analysis::RetType Analysis_Clustering::Setup(ArgList& analyzeArgs, AnalysisSetup } inputDsets += tempDSL; } - for (DataSetList::const_iterator ds = inputDsets.begin(); ds != inputDsets.end(); ++ds) { - // Clustering only allowed on 1D data sets. - if ( (*ds)->Ndim() != 1 ) { - mprinterr("Error: Clustering only allowed on 1D data sets, %s is %zuD.\n", - (*ds)->legend(), (*ds)->Ndim()); - return Analysis::ERR; - } - cluster_dataset_.push_back( *ds ); - } - metric_ = ClusterList::DATA; - } else { - int usedme = (int)analyzeArgs.hasKey("dme"); - int userms = (int)analyzeArgs.hasKey("rms"); - int usesrms = (int)analyzeArgs.hasKey("srmsd"); - if (usedme + userms + usesrms > 1) { - mprinterr("Error: Specify either 'dme', 'rms', or 'srmsd'.\n"); - return Analysis::ERR; - } - if (usedme) metric_ = ClusterList::DME; - else if (userms) metric_ = ClusterList::RMS; - else if (usesrms) metric_ = ClusterList::SRMSD; - } - // Get all loaded reference structures - if (analyzeArgs.hasKey("assignrefs")) { - refs_ = setup.DSL().GetSetsOfType("*", DataSet::REF_FRAME); - if (refs_.empty()) { - mprinterr("Error: 'assignrefs' specified but no references loaded.\n"); - return Analysis::ERR; - } - refCut_ = analyzeArgs.getKeyDouble("refcut", 1.0); - refmaskexpr_ = analyzeArgs.GetStringKey("refmask"); - } - // Get clustering algorithm - if (CList_ != 0) delete CList_; - CList_ = 0; - if (analyzeArgs.hasKey("hieragglo")) CList_ = new Cluster_HierAgglo(); - else if (analyzeArgs.hasKey("dbscan")) CList_ = new Cluster_DBSCAN(); - else if (analyzeArgs.hasKey("dpeaks")) CList_ = new Cluster_DPeaks(); - else if (analyzeArgs.hasKey("kmeans") || - analyzeArgs.hasKey("means" )) CList_ = new Cluster_Kmeans(); - else if (analyzeArgs.hasKey("readinfo") || - analyzeArgs.hasKey("readtxt")) CList_ = new Cluster_ReadInfo(); - else { - mprintf("Warning: No clustering algorithm specified; defaulting to 'hieragglo'\n"); - CList_ = new Cluster_HierAgglo(); - } - if (CList_ == 0) return Analysis::ERR; - CList_->SetDebug(debug_); - // Get algorithm-specific keywords - if (CList_->SetupCluster( analyzeArgs )) return Analysis::ERR; - // --------------------------------------------- - // Options for loading/saving pairwise distance file - DataSet::DataType pw_type = DataSet::CMATRIX; - std::string pw_typeString = analyzeArgs.GetStringKey("pairwisecache"); - if (!pw_typeString.empty()) { - if (pw_typeString == "mem") - pw_type = DataSet::CMATRIX; - else if (pw_typeString == "disk") - pw_type = DataSet::CMATRIX_DISK; - else if (pw_typeString == "none") - pw_type = DataSet::CMATRIX_NOMEM; - else { - mprinterr("Error: Unrecognized option for 'pairwisecache' ('%s')\n", pw_typeString.c_str()); - return Analysis::ERR; - } - } - std::string pairdistname = analyzeArgs.GetStringKey("pairdist"); - DataFile::DataFormatType pairdisttype = DataFile::UNKNOWN_DATA; - bool load_pair = analyzeArgs.hasKey("loadpairdist"); - bool save_pair = analyzeArgs.hasKey("savepairdist"); - pw_dist_ = 0; - if (load_pair || - (!save_pair && !pairdistname.empty())) - { - // If 'loadpairdist' specified or 'pairdist' specified and 'savepairdist' - // not specified, we either want to load from file or use an existing - // data set. - if (pairdistname.empty()) { - pairdistname = PAIRDISTFILE_; - pairdisttype = PAIRDISTTYPE_; - } - // First check if a Cmatrix data set exists - pw_dist_ = setup.DSL().FindSetOfType( pairdistname, DataSet::CMATRIX ); - if (pw_dist_ != 0) { - mprintf("\tUsing existing pairwise set '%s'\n", pw_dist_->legend()); - // Next check if file exists - } else if (File::Exists( pairdistname )) { - mprintf("\tLoading pairwise distances from file '%s'\n", pairdistname.c_str()); - DataFile dfIn; - if (dfIn.ReadDataIn( pairdistname, ArgList(), setup.DSL() )) return Analysis::ERR; - pw_dist_ = setup.DSL().GetDataSet( pairdistname ); - if (pw_dist_ == 0) return Analysis::ERR; - } else - pairdisttype = PAIRDISTTYPE_; - if (pw_dist_ == 0) { - // Just 'pairdist' specified or loadpairdist specified and set/file not found. - // If the file (or dataset) does not yet exist we will assume we want to save. - mprintf("Warning: 'loadpairdist' specified but '%s' not found; will save distances.\n", - pairdistname.c_str()); - save_pair = true; - } - } - // Create file for saving pairwise distances - pwd_file_ = 0; - if (save_pair) { - if (pairdistname.empty()) { - pairdistname = PAIRDISTFILE_; - pairdisttype = PAIRDISTTYPE_; - } - pwd_file_ = setup.DFL().AddDataFile( pairdistname, pairdisttype, ArgList() ); } - // --------------------------------------------- - // Get keywords - useMass_ = analyzeArgs.hasKey("mass"); - includeSieveInCalc_ = analyzeArgs.hasKey("includesieveincalc"); - if (includeSieveInCalc_) - mprintf("Warning: 'includesieveincalc' may be very slow.\n"); - sieveSeed_ = analyzeArgs.getKeyInt("sieveseed", -1); - sieve_ = analyzeArgs.getKeyInt("sieve", 1); - if (sieve_ < 1) { - mprinterr("Error: 'sieve <#>' must be >= 1 (%i)\n", sieve_); - return Analysis::ERR; - } - if (analyzeArgs.hasKey("random") && sieve_ > 1) - sieve_ = -sieve_; // negative # indicates random sieve - // Override sieve value - if (pw_dist_ != 0) { - if (sieve_ == 1) { - mprintf("Warning: Using sieve options from specified pairwise distance set '%s'\n", - pw_dist_->legend()); - sieve_ = ((DataSet_Cmatrix*)pw_dist_)->SieveValue(); - } else if (sieve_ != ((DataSet_Cmatrix*)pw_dist_)->SieveValue()) { - mprintf("Warning: Specified sieve options do not match pairwise distance set '%s'\n", - pw_dist_->legend()); - } - } - if (analyzeArgs.hasKey("pwrecalc")) - pw_mismatch_fatal_ = false; - halffile_ = analyzeArgs.GetStringKey("summarysplit"); - if (halffile_.empty()) // For backwards compat. - halffile_ = analyzeArgs.GetStringKey("summaryhalf"); - if (!halffile_.empty()) { - ArgList splits( analyzeArgs.GetStringKey("splitframe"), "," ); - if (!splits.empty()) { - splitFrames_.clear(); - int sf = splits.getNextInteger(-1); // User frame #s start at 1 - while (sf > 0) { - splitFrames_.push_back( sf ); - sf = splits.getNextInteger(-1); - } - if ((int)splitFrames_.size() < splits.Nargs()) { - mprinterr("Error: Invalid split frame arguments.\n"); - splits.CheckForMoreArgs(); - return Analysis::ERR; - } - } - } - std::string bestRepStr = analyzeArgs.GetStringKey("bestrep"); - if (bestRepStr.empty()) { - // For sieving, cumulative can get very expensive. Default to centroid. - if (sieve_ != 1) - bestRep_ = CENTROID; - else - bestRep_ = CUMULATIVE; - } else { - if (bestRepStr == "cumulative") - bestRep_ = CUMULATIVE; - else if (bestRepStr == "centroid") - bestRep_ = CENTROID; - else if (bestRepStr == "cumulative_nosieve") - bestRep_ = CUMULATIVE_NOSIEVE; - else { - mprinterr("Error: Invalid 'bestRep' option (%s)\n", bestRepStr.c_str()); + // If 'crdset' specified or if 'nocoords' *not* specified, attempt to get + // COORDS DataSet from master DataSetList. + std::string setname = analyzeArgs.GetStringKey("crdset"); + if (!setname.empty() || !analyzeArgs.hasKey("nocoords")) { + coords = (DataSet_Coords*)setup.DSL().FindCoordsSet( setname ); + if (coords == 0) { + mprinterr("Error: Could not locate COORDS set corresponding to %s\n", + setname.c_str()); return Analysis::ERR; } - } - nRepsToSave_ = analyzeArgs.getKeyInt("savenreps", 1); - if (nRepsToSave_ < 1) { - mprinterr("Error: 'savenreps' must be > 0\n"); - return Analysis::ERR; - } - if (analyzeArgs.hasKey("drawgraph")) - drawGraph_ = 1; - else if (analyzeArgs.hasKey("drawgraph3d")) - drawGraph_ = 2; - else - drawGraph_ = 0; - draw_maxit_ = analyzeArgs.getKeyInt("draw_maxit", 1000); - draw_tol_ = analyzeArgs.getKeyDouble("draw_tol", 1.0E-5); - - DataFile* cnumvtimefile = setup.DFL().AddDataFile(analyzeArgs.GetStringKey("out"), analyzeArgs); - DataFile* clustersvtimefile = setup.DFL().AddDataFile(analyzeArgs.GetStringKey("clustersvtime"), - analyzeArgs); - windowSize_ = analyzeArgs.getKeyInt("cvtwindow", 0); - cpopvtimefile_ = setup.DFL().AddDataFile(analyzeArgs.GetStringKey("cpopvtime"), analyzeArgs); - clusterinfo_ = analyzeArgs.GetStringKey("info"); - summaryfile_ = analyzeArgs.GetStringKey("summary"); - nofitrms_ = analyzeArgs.hasKey("nofit"); - grace_color_ = analyzeArgs.hasKey("gracecolor"); - calc_lifetimes_ = analyzeArgs.hasKey("lifetime"); - if (cpopvtimefile_ != 0) { - if (analyzeArgs.hasKey("normpop")) - norm_pop_ = CLUSTERPOP; - else if (analyzeArgs.hasKey("normframe")) - norm_pop_ = FRAME; - else - norm_pop_ = NONE; - } - sil_file_ = analyzeArgs.GetStringKey("sil"); - - // Output trajectory stuff - writeRepFrameNum_ = analyzeArgs.hasKey("repframe"); - GetClusterTrajArgs(analyzeArgs, "clusterout", "clusterfmt", clusterfile_, clusterfmt_); - GetClusterTrajArgs(analyzeArgs, "singlerepout", "singlerepfmt", singlerepfile_, singlerepfmt_); - GetClusterTrajArgs(analyzeArgs, "repout", "repfmt", reptrajfile_, reptrajfmt_); - GetClusterTrajArgs(analyzeArgs, "avgout", "avgfmt", avgfile_, avgfmt_); - - // Get the mask string - maskexpr_ = analyzeArgs.GetMaskNext(); - if (!refs_.empty() && refmaskexpr_.empty()) { - refmaskexpr_ = maskexpr_; - if (refmaskexpr_.empty()) { - refmaskexpr_.assign("!@H="); - mprintf("Warning: 'assignrefs' specified but no 'refmask' given.\n" - "Warning: Using default mask expression: '%s'\n", refmaskexpr_.c_str()); - } + // If 'data' was not specified, this is the set we will cluster on. + if (dataSetname.empty()) + inputDsets.AddCopyOfSet( coords ); } - // Output option for cluster info - suppressInfo_ = analyzeArgs.hasKey("noinfo"); + if (control_.SetupClustering(inputDsets, coords, analyzeArgs, setup.DSL(), setup.DFL(), debugIn)) + return Analysis::ERR; - // Dataset to store cluster number v time - cnumvtime_ = setup.DSL().AddSet(DataSet::INTEGER, analyzeArgs.GetStringNext(), "Cnum"); - if (cnumvtime_==0) return Analysis::ERR; - if (cnumvtimefile != 0) cnumvtimefile->AddDataSet( cnumvtime_ ); - // If no pairwise distance matrix yet, allocate one - if (pw_dist_ == 0) { - MetaData md; - if (pairdistname.empty()) - md = MetaData( cnumvtime_->Meta().Name(), "PWD" ); - else - md = MetaData( pairdistname ); - if (pw_type == DataSet::CMATRIX_DISK) - md.SetFileName("CpptrajPairwiseCache"); - pw_dist_ = setup.DSL().AddSet(pw_type, md); - if (pw_dist_ == 0) return Analysis::ERR; - } + control_.Info(); - // DataSet for # clusters seen v time - if (clustersvtimefile != 0) { - if (windowSize_ < 2) { - mprinterr("Error: For # clusters seen vs time, cvtwindow must be specified and > 1\n"); - return Analysis::ERR; - } - clustersVtime_ = setup.DSL().AddSet(DataSet::INTEGER, - MetaData(cnumvtime_->Meta().Name(), "NCVT")); - if (clustersVtime_ == 0) return Analysis::ERR; - clustersvtimefile->AddDataSet( clustersVtime_ ); - } - // Save master DSL for Cpopvtime masterDSL_ = setup.DslPtr(); - mprintf(" CLUSTER:"); - if (coords_ != 0) mprintf(" Using coords dataset %s,", coords_->legend()); - mprintf(" clustering using"); - if ( metric_ != ClusterList::DATA ) { - mprintf(" %s", ClusterList::MetricString( metric_ )); - if (!maskexpr_.empty()) - mprintf(" (mask [%s])",maskexpr_.c_str()); - else - mprintf(" (all atoms)"); - if (useMass_) - mprintf(", mass-weighted"); - if (nofitrms_) - mprintf(", no fitting"); - else - mprintf(" best-fit"); - } else { - if (cluster_dataset_.size() == 1) - mprintf(" dataset %s", cluster_dataset_[0]->legend()); - else - mprintf(" %zu datasets.", cluster_dataset_.size()); - } - mprintf("\n"); - CList_->ClusteringInfo(); - if (sieve_ > 1) - mprintf("\tInitial clustering sieve value is %i frames.\n", sieve_); - else if (sieve_ < -1) { - mprintf("\tInitial clustering will be randomly sieved (with value %i)", -sieve_); - if (sieveSeed_ > 0) mprintf(" using random seed %i", sieveSeed_); - mprintf(".\n"); - } - if (sieve_ != 1) { - if (includeSieveInCalc_) - mprintf("\tAll frames (including sieved) will be used to calc within-cluster average.\n"); - else - mprintf("\tOnly non-sieved frames will be used to calc within-cluster average.\n"); - } - if (cnumvtimefile != 0) - mprintf("\tCluster # vs time will be written to %s\n", cnumvtimefile->DataFilename().base()); - if (clustersvtimefile != 0) - mprintf("\t# clusters seen vs time will be written to %s\n", - clustersvtimefile->DataFilename().base()); - if (cpopvtimefile_ != 0) { - mprintf("\tCluster pop vs time will be written to %s", cpopvtimefile_->DataFilename().base()); - if (norm_pop_==CLUSTERPOP) mprintf(" (normalized by cluster size)"); - else if (norm_pop_==FRAME) mprintf(" (normalized by frame)"); - mprintf("\n"); - } - if (grace_color_) - mprintf("\tGrace color instead of cluster number (1-15) will be saved.\n"); - if (calc_lifetimes_) - mprintf("\tCluster lifetime data sets will be calculated.\n"); - mprintf("\tPairwise distance data set is '%s'\n", pw_dist_->legend()); - if (pw_dist_->Type() == DataSet::CMATRIX_NOMEM) - mprintf("\tPairwise distances will not be cached (will slow clustering calcs)\n"); - else if (pw_dist_->Type() == DataSet::CMATRIX_DISK) - mprintf("\tPairwise distances will be cached to disk (will slow clustering calcs)\n"); - if (pw_dist_->Size() > 0) { - if (pw_mismatch_fatal_) - mprintf("\tCalculation will be halted if # frames does not match '%s'\n", - pw_dist_->legend()); - else - mprintf("\tPairwise distances will be recalculated if # frames does not match '%'s\n", - pw_dist_->legend()); - } - if (pwd_file_ != 0) - mprintf("\tSaving pair-wise distances to '%s'\n", pwd_file_->DataFilename().full()); - if (!clusterinfo_.empty()) - mprintf("\tCluster information will be written to %s\n",clusterinfo_.c_str()); - if (!summaryfile_.empty()) - mprintf("\tSummary of cluster results will be written to %s\n",summaryfile_.c_str()); - if (!sil_file_.empty()) { - mprintf("\tFrame silhouettes will be written to %s.frame.dat, cluster silhouettes\n" - "\t will be written to %s.cluster.dat\n", sil_file_.c_str(), sil_file_.c_str()); - if (sieve_ != 1) { - if (includeSieveInCalc_) - mprintf("\tSilhouette calculation will use all frames.\n"); - else - mprintf("\tSilhouette calculation will use non-sieved frames ONLY.\n"); - } - } - if (!halffile_.empty()) { - mprintf("\tSummary comparing parts of trajectory data for clusters will be written to %s\n", - halffile_.c_str()); - if (!splitFrames_.empty()) { - mprintf("\t\tFrames will be split at:"); - for (std::vector::const_iterator f = splitFrames_.begin(); f != splitFrames_.end(); ++f) - mprintf(" %i", *f); - mprintf("\n"); - } else - mprintf("\t\tFrames will be split at the halfway point.\n"); - } - mprintf("\tRepresentative frames will be chosen by"); - switch (bestRep_) { - case CUMULATIVE: mprintf(" lowest cumulative distance to all other frames.\n"); break; - case CENTROID : mprintf(" closest distance to cluster centroid.\n"); break; - case CUMULATIVE_NOSIEVE: - mprintf(" lowest cumulative distance to all other frames (ignore sieved frames).\n"); - break; - } - if (nRepsToSave_ > 1) - mprintf("\tThe top %i representative frames will be determined.\n", nRepsToSave_); - if (!clusterfile_.empty()) - mprintf("\tCluster trajectories will be written to %s, format %s\n", - clusterfile_.c_str(), TrajectoryFile::FormatString(clusterfmt_)); - if (!singlerepfile_.empty()) - mprintf("\tCluster representatives will be written to 1 traj (%s), format %s\n", - singlerepfile_.c_str(), TrajectoryFile::FormatString(singlerepfmt_)); - if (!reptrajfile_.empty()) { - mprintf("\tCluster representatives will be written to separate trajectories,\n"); - mprintf("\t\tprefix (%s), format %s",reptrajfile_.c_str(), - TrajectoryFile::FormatString(reptrajfmt_)); - if (writeRepFrameNum_) mprintf(", with frame #s"); - mprintf("\n"); - } - if (!avgfile_.empty()) - mprintf("\tAverage structures for clusters will be written to %s, format %s\n", - avgfile_.c_str(), TrajectoryFile::FormatString(avgfmt_)); - if (!refs_.empty()) - mprintf("\tClusters will be identified with loaded reference structures if RMSD\n" - "\t (mask '%s') to representative frame is < %g Ang.\n", refmaskexpr_.c_str(),refCut_); - if (drawGraph_ > 0) - mprintf("\tEXPERIMENTAL: Force-directed graph will be drawn from pairwise distances.\n" - "\t Max iterations= %i, min tolerance= %g\n", - draw_maxit_, draw_tol_); - return Analysis::OK; + } -/** This is where the clustering is actually performed. First the distances - * between each frame are calculated. Then the clustering routine is called. - */ -// TODO: Need to update save to indicate distance type -// NOTE: Should distances be saved only if load_pair? +// Analysis_Clustering::Analyze() Analysis::RetType Analysis_Clustering::Analyze() { - Timer cluster_setup; - Timer cluster_pairwise; - Timer cluster_cluster; - Timer cluster_post; - Timer cluster_total; - cluster_total.Start(); - mprintf("\tStarting clustering.\n"); - cluster_setup.Start(); - // If no dataset specified, use COORDS - if (cluster_dataset_.empty()) { - if (coords_ == 0) { - mprinterr("Error: No data to cluster on.\n"); - return Analysis::ERR; - } - cluster_dataset_.push_back( (DataSet*)coords_ ); - } - // Test that cluster data set contains data - unsigned int clusterDataSetSize = cluster_dataset_[0]->Size(); - if (clusterDataSetSize < 1) { - mprinterr("Error: cluster data set %s does not contain data.\n", - cluster_dataset_[0]->legend()); + Timer t_total; + t_total.Start(); + if (control_.Run() != 0) { + mprinterr("Error: Clustering failed.\n"); return Analysis::ERR; } - // If more than one data set, make sure they are all the same size. - for (ClusterDist::DsArray::iterator ds = cluster_dataset_.begin(); - ds != cluster_dataset_.end(); ++ds) - { - if ((*ds)->Size() != clusterDataSetSize) { - mprinterr("Error: data set '%s' size (%zu) != first data set '%s' size (%u)\n", - (*ds)->legend(), (*ds)->Size(), - cluster_dataset_[0]->legend(), clusterDataSetSize); - return Analysis::ERR; - } - } - // If no coordinates were specified, disable coordinate output types - bool has_coords = true; - if (coords_ == 0 || coords_->Size() < 1) { - mprintf("Warning: No coordinates or associated coordinate data set is empty.\n" - "Warning: Disabling coordinate output.\n"); - has_coords = false; - } - cluster_setup.Stop(); - - // Set up cluster distance calculation - if (CList_->SetupCdist( cluster_dataset_, metric_, nofitrms_, useMass_, maskexpr_ )) - return Analysis::ERR; - - // Check or calculate pairwise distances between frames - cluster_pairwise.Start(); - // Do some sanity checking first - if (pw_dist_ == 0) { - mprinterr("Internal Error: Empty cluster matrix.\n"); + // Output + if (control_.Output(*masterDSL_) != 0) { + mprinterr("Error: Cluster output failed.\n"); return Analysis::ERR; } - if (pw_dist_->Group() != DataSet::CLUSTERMATRIX) { - mprinterr("Internal Error: Wrong cluster matrix type.\n"); - return Analysis::ERR; - } - if (pw_dist_->Size() > 0) { - // Check if existing pw dist matrix matches expected size. If not, need to - // allocate a new data set and recalculate. - int sval = sieve_; - if (sval < 0) sval = -sval; - unsigned int expected_nrows = cluster_dataset_[0]->Size() / (unsigned int)sval; - if ( (cluster_dataset_[0]->Size() % (unsigned int)sval) != 0 ) - expected_nrows++; - if ( ((DataSet_Cmatrix*)pw_dist_)->Nrows() != expected_nrows ) { - if (sval == 1) { - // No sieve value specified by user. - if ( ((DataSet_Cmatrix*)pw_dist_)->SieveValue() != 1 ) { - // Cluster matrix is sieved. - mprintf("Warning: Sieved ClusterMatrix has %zu rows, expected %u; did you forget\n" - "Warning: to specify 'sieve <#>'?\n", - ((DataSet_Cmatrix*)pw_dist_)->Nrows(), expected_nrows); - } else { - // Cluster matrix is not sieved. - mprintf("Warning: ClusterMatrix has %zu rows, expected %u.\n", - ((DataSet_Cmatrix*)pw_dist_)->Nrows(), expected_nrows); - } - } else { - // Sieve value specified by user. - if ( ((DataSet_Cmatrix*)pw_dist_)->SieveValue() != 1 ) { - // Cluster matrix is sieved. - mprintf("Warning: Sieved ClusterMatrix has %zu rows, expected %u based on\n" - "Warning: specified sieve value (%i)\n", - ((DataSet_Cmatrix*)pw_dist_)->Nrows(), expected_nrows, sval); - } else { - // Cluster matrix is not sieved. - mprintf("Warning: ClusterMatrix has %zu rows, expected %u based on\n" - "Warning: specified sieve value (%i).\n", - ((DataSet_Cmatrix*)pw_dist_)->Nrows(), expected_nrows, sval); - } - } - if (pw_mismatch_fatal_) { - mprinterr("Error: Input pairwise matrix '%s' size (%zu) does not match expected size (%u)\n" - "Error: Check that input number of frames and sieve value are consistent.\n", - pw_dist_->legend(), - ((DataSet_Cmatrix*)pw_dist_)->Nrows(), expected_nrows); - mprinterr("Error: Check warnings in cpptraj output for more details.\n"); - return Analysis::ERR; - } - mprintf("Warning: Recalculating matrix.\n"); - pw_dist_ = masterDSL_->AddSet(DataSet::CMATRIX, "", "CMATRIX"); - if (pw_dist_ == 0) return Analysis::ERR; - } - } - if (CList_->CalcFrameDistances( pw_dist_, cluster_dataset_, sieve_, sieveSeed_ )) - return Analysis::ERR; - // If we want to save the pairwise distances add to file now - if (pwd_file_ != 0) - pwd_file_->AddDataSet( pw_dist_ ); - cluster_pairwise.Stop(); - - // Cluster - cluster_cluster.Start(); - CList_->Cluster(); - cluster_cluster.Stop(); - cluster_post.Start(); - Timer cluster_post_renumber; - Timer cluster_post_bestrep; - Timer cluster_post_info; - Timer cluster_post_summary; - Timer cluster_post_coords; - if (CList_->Nclusters() > 0) { - // Sort clusters and renumber; also finds centroids. If sieving, - // add remaining frames. - cluster_post_renumber.Start(); - CList_->Renumber( (sieve_ != 1) ); - cluster_post_renumber.Stop(); - // Find best representative frames for each cluster. - cluster_post_bestrep.Start(); - switch (bestRep_) { - case CUMULATIVE: CList_->FindBestRepFrames_CumulativeDist(nRepsToSave_); break; - case CENTROID : CList_->FindBestRepFrames_Centroid(nRepsToSave_); break; - case CUMULATIVE_NOSIEVE: CList_->FindBestRepFrames_NoSieve_CumulativeDist(nRepsToSave_); break; - } - cluster_post_bestrep.Stop(); - // DEBUG - if (debug_ > 0) { - mprintf("\nFINAL CLUSTERS:\n"); - CList_->PrintClusters(); - } - // Attempt to assign reference names to clusters if any specified. - if (!refs_.empty()) { - if (has_coords) - AssignRefsToClusters( *CList_ ); - else - mprintf("Warning: References were specified but no COORDS. Cannot assign ref names.\n"); - } - - // Print ptraj-like cluster info. - // If no filename is written and no noinfo, some info will still be written to STDOUT - if (!suppressInfo_) { - cluster_post_info.Start(); - CList_->PrintClustersToFile(clusterinfo_); - cluster_post_info.Stop(); - } - - // Calculate cluster silhouette - if (!sil_file_.empty()) - CList_->CalcSilhouette( sil_file_, includeSieveInCalc_ ); - - // Print a summary of clusters - if (!summaryfile_.empty()) { - cluster_post_summary.Start(); - CList_->Summary(summaryfile_, includeSieveInCalc_); - cluster_post_summary.Stop(); - } - - // Print a summary comparing first half to second half of data for clusters - if (!halffile_.empty()) { - // If no split frames were specified, use halfway point. - if (splitFrames_.empty()) - splitFrames_.push_back( clusterDataSetSize / 2 ); - // Check that none of the split values are invalid. - std::vector actualSplitFrames; - for (std::vector::const_iterator f = splitFrames_.begin(); - f != splitFrames_.end(); ++f) - if ( *f < 1 || *f >= (int)clusterDataSetSize ) - mprintf("Warning: split frame %i is out of bounds; ignoring.\n", *f); - else - actualSplitFrames.push_back( *f ); - CList_->Summary_Part(halffile_, actualSplitFrames); - } - - // Create cluster v time data from clusters. - CreateCnumvtime( *CList_, clusterDataSetSize ); - - // TEST: Draw graph based on point distances - if (drawGraph_ > 0) - CList_->DrawGraph( drawGraph_ == 2, cnumvtime_, draw_tol_, draw_maxit_ ); - - // Create # clusters seen v time data. - if (clustersVtime_ != 0) - NclustersObserved( *CList_, clusterDataSetSize ); - - // Create cluster pop v time plots - if (cpopvtimefile_ != 0) - CreateCpopvtime( *CList_, clusterDataSetSize ); - - // Create cluster lifetime DataSets - if (calc_lifetimes_) - ClusterLifetimes( *CList_, clusterDataSetSize ); - - // Change cluster num v time to grace-compatible colors if specified. - if (grace_color_) { - DataSet_integer& cnum_temp = static_cast( *cnumvtime_ ); - for (unsigned int idx = 0; idx != cnum_temp.Size(); idx++) - { - cnum_temp.AddVal(idx, 1); - if (cnum_temp[idx] > 15) cnum_temp.SetElement(idx, 15); - } - } - // Coordinate output. - if (has_coords) { - cluster_post_coords.Start(); - // Write clusters to trajectories - if (!clusterfile_.empty()) - WriteClusterTraj( *CList_ ); - // Write all representative frames to a single traj - if (!singlerepfile_.empty()) - WriteSingleRepTraj( *CList_ ); - // Write all representative frames to separate trajs - if (!reptrajfile_.empty()) - WriteRepTraj( *CList_ ); - // Write average structures for each cluster to separate files. - if (!avgfile_.empty()) - WriteAvgStruct( *CList_ ); - cluster_post_coords.Stop(); - } - } else - mprintf("\tNo clusters found.\n"); - cluster_post.Stop(); - cluster_total.Stop(); - // Timing data - mprintf("\tCluster timing data:\n"); - cluster_setup.WriteTiming(1, " Cluster Init. :", cluster_total.Total()); - cluster_pairwise.WriteTiming(1, " Pairwise Calc.:", cluster_total.Total()); - cluster_cluster.WriteTiming(1, " Clustering :", cluster_total.Total()); -# ifdef TIMER - CList_->Timing( cluster_cluster.Total() ); -# endif - cluster_post.WriteTiming(1, " Cluster Post. :", cluster_total.Total()); - cluster_post_renumber.WriteTiming(2, "Cluster renumbering/sieve restore", cluster_post.Total()); - cluster_post_bestrep.WriteTiming(2, "Find best rep.", cluster_post.Total()); - cluster_post_info.WriteTiming(2, "Info calc", cluster_post.Total()); - cluster_post_summary.WriteTiming(2, "Summary calc", cluster_post.Total()); - cluster_post_coords.WriteTiming(2, "Coordinate writes", cluster_post.Total()); - cluster_total.WriteTiming(1, "Total:"); + t_total.Stop(); + control_.Timing(t_total.Total()); return Analysis::OK; } - -// ----------------------------------------------------------------------------- -void Analysis_Clustering::AssignRefsToClusters( ClusterList& CList ) const { - // Pre-center all reference coords at the origin. No need to store trans vectors. - std::vector refFrames; - refFrames.reserve( refs_.size() ); - for (unsigned int idx = 0; idx != refs_.size(); idx++) { - AtomMask rMask( refmaskexpr_ ); - DataSet_Coords_REF* REF_ds = (DataSet_Coords_REF*)refs_[idx]; - if ( REF_ds->Top().SetupIntegerMask( rMask, REF_ds->RefFrame() ) ) { - mprintf("Warning: Could not set up mask for reference '%s'\n", REF_ds->legend()); - continue; - } - refFrames.push_back( Frame(REF_ds->RefFrame(), rMask) ); - refFrames.back().CenterOnOrigin( useMass_ ); - } - // For each cluster, assign the reference name with the lowest RMSD - // to the representative frame that is below the cutoff. - AtomMask tMask( refmaskexpr_ ); - if (coords_->Top().SetupIntegerMask( tMask )) { - mprinterr("Error: Could not set up mask for assigning references.\n"); - return; - } - Frame TGT( coords_->AllocateFrame(), tMask ); - unsigned int cidx = 0; - for (ClusterList::cluster_it cluster = CList.begin(); - cluster != CList.end(); ++cluster, ++cidx) - { - coords_->GetFrame( cluster->BestRepFrame(), TGT, tMask ); - double minRms = TGT.RMSD_CenteredRef( refFrames[0], useMass_ ); - unsigned int minIdx = 0; - for (unsigned int idx = 1; idx < refs_.size(); idx++) { - double rms = TGT.RMSD_CenteredRef( refFrames[idx], useMass_ ); - if (rms < minRms) { - minRms = rms; - minIdx = idx; - } - } - if (minRms < refCut_) { - //mprintf("DEBUG: Assigned cluster %i to reference \"%s\" (%g)\n", cidx, - // refs_[minIdx]->Meta().Name().c_str(), minRms); - cluster->SetNameAndRms( refs_[minIdx]->Meta().Name(), minRms ); - } else { - //mprintf("DEBUG: Cluster %i was closest to reference \"(%s)\" (%g)\n", cidx, - // refs_[minIdx]->Meta().Name().c_str(), minRms); - cluster->SetNameAndRms( "(" + refs_[minIdx]->Meta().Name() + ")", minRms ); - } - } -} - -// ----------------------------------------------------------------------------- -// Analysis_Clustering::CreateCnumvtime() -/** Put cluster number vs frame into dataset. */ -void Analysis_Clustering::CreateCnumvtime( ClusterList const& CList, unsigned int maxFrames ) { - // FIXME: - // Cast generic DataSet for cnumvtime back to integer dataset to - // access specific integer dataset functions for resizing and [] - // operator. Should this eventually be generic to all atomic DataSets? - DataSet_integer& cnum_temp = static_cast( *cnumvtime_ ); - // Make all clusters start at -1. This way cluster algorithms that - // have noise points (i.e. no cluster assigned) will be distinguished. - cnum_temp.Assign( maxFrames, -1 ); - - for (ClusterList::cluster_iterator C = CList.begincluster(); - C != CList.endcluster(); C++) - { - //mprinterr("Cluster %i:\n",CList->CurrentNum()); - int cnum = (*C).Num(); - // Loop over all frames in the cluster - for (ClusterNode::frame_iterator frame = (*C).beginframe(); - frame != (*C).endframe(); frame++) - { - //mprinterr("%i,",*frame); - cnum_temp.SetElement(*frame, cnum); - } - //mprinterr("\n"); - //break; - } -} - -// Analysis_Clustering::CreateCpopvtime() -// NOTE: Should not be called if cpopvtimefile is NULL -void Analysis_Clustering::CreateCpopvtime( ClusterList const& CList, unsigned int maxFrames ) { - mprintf("\tCalculating cluster population vs time for each cluster.\n"); - // Set up output data sets - std::vector Cpop; - MetaData md(cnumvtime_->Meta().Name(), "Pop"); - DataSet::SizeArray dsize(1, maxFrames); - for (int cnum = 0; cnum < CList.Nclusters(); ++cnum) { - md.SetIdx( cnum ); - DataSet_float* ds = (DataSet_float*)masterDSL_->AddSet( DataSet::FLOAT, md ); - if (ds == 0) { - mprinterr("Error: Could not allocate cluster pop v time DataSet.\n"); - return; - } - ds->Allocate( dsize ); - Cpop.push_back( ds ); - // SANITY CHECK - if (cpopvtimefile_ != 0) - cpopvtimefile_->AddDataSet( ds ); - } - int cnum = 0; - // Loop over all clusters - for (ClusterList::cluster_iterator C = CList.begincluster(); C != CList.endcluster(); ++C, ++cnum) - { - DataSet_float& pvt = static_cast( *(Cpop[cnum]) ); - float pop = 0.0; - // Loop over all frames in cluster - for (ClusterNode::frame_iterator f = C->beginframe(); f != C->endframe(); ++f) - { - if (*f > (int)pvt.Size()) - pvt.Resize( *f, pop ); - pop = pop + 1.0; - pvt[*f] = pop; - } - // Ensure pop v time set is maxFrames long - if (pvt.Size() < maxFrames) - pvt.Resize( maxFrames, pop ); - // Normalization - if (norm_pop_ == CLUSTERPOP) { - float norm = 1.0 / (float)C->Nframes(); - for (unsigned int frm = 0; frm < maxFrames; ++frm) - pvt[frm] = pvt[frm] * norm; - } else if (norm_pop_ == FRAME) { - float norm = 1.0; - for (unsigned int frm = 0; frm < maxFrames; ++frm) - { - pvt[frm] = pvt[frm] / norm; - norm = norm + 1.0; - } - } - } -} - -// Analysis_Clustering::ClusterLifetimes() -void Analysis_Clustering::ClusterLifetimes( ClusterList const& CList, unsigned int maxFrames ) { - // Set up output data sets. TODO: use ChildDSL - std::vector DSL; - MetaData md(cnumvtime_->Meta().Name(), "Lifetime"); - for (int cnum = 0; cnum < CList.Nclusters(); ++cnum) { - md.SetIdx( cnum ); - DSL.push_back((DataSet_integer*) masterDSL_->AddSet( DataSet::INTEGER, md)); - if (DSL.back() == 0) { - mprinterr("Error: Could not allocate cluster lifetime DataSet.\n"); - return; - } - DSL.back()->Resize( maxFrames ); - } - // For each frame, assign cluster frame belongs to 1. - DataSet_integer const& cnum_temp = static_cast(*cnumvtime_); - for (unsigned int frame = 0; frame < maxFrames; ++frame) { - int cluster_num = cnum_temp[frame]; - // Noise points are -1 - if (cluster_num > -1) - DSL[ cluster_num ]->SetElement( frame, 1 ); - } -} - -/** Determine how many different clusters are observed within a given time - * window. - */ -void Analysis_Clustering::NclustersObserved( ClusterList const& CList, unsigned int maxFrames ) { - DataSet_integer const& CVT = static_cast( *cnumvtime_ ); - if (CVT.Size() < 1 || CList.Nclusters() < 1) return; - int dataIdx = 0; - // True if cluster was observed during window - std::vector observed( CList.Nclusters(), false ); - for (unsigned int frame = 0; frame < maxFrames; frame++) { - if (CVT[frame] != -1) - observed[ CVT[frame] ] = true; - if ( ((frame+1) % windowSize_) == 0 ) { - // Count # observed clusters - int nClustersObserved = 0; - for (std::vector::iterator ob = observed.begin(); ob != observed.end(); ++ob) - if ( *ob ) { - ++nClustersObserved; - *ob = false; - } - //mprintf("DEBUG: WINDOW at frame %i; %i clusters observed\n", frame+1, nClustersObserved); - clustersVtime_->Add( dataIdx++, &nClustersObserved ); - } - } -/* - int currentCluster = CVT[0]; - int nClustersObserved = 1; - for (int frame = 1; frame < maxFrames; frame++) { - // Do not count noise as a cluster. - if (CVT[frame] != currentCluster && CVT[frame] != -1) { - ++nClustersObserved; - currentCluster = CVT[frame]; - } - mprintf("DEBUG: %i %i\n", frame+1, nClustersObserved); - if ( ((frame+1) % windowSize_) == 0 ) { - mprintf("DEBUG: WINDOW\n"); - clustersVtime_->Add( dataIdx++, &nClustersObserved ); - nClustersObserved = 1; - } - } -*/ - clustersVtime_->SetDim(Dimension::X, Dimension(windowSize_, windowSize_, "Frame")); -} - -// ---------- Cluster Coordinate Output Routines ------------------------------- -// Analysis_Clustering::WriteClusterTraj() -/** Write frames in each cluster to a trajectory file. */ -void Analysis_Clustering::WriteClusterTraj( ClusterList const& CList ) { - Topology* clusterparm = coords_->TopPtr(); - // Loop over all clusters - for (ClusterList::cluster_iterator C = CList.begincluster(); - C != CList.endcluster(); ++C) - { - // Create filename based on cluster number. - int cnum = C->Num(); - std::string cfilename = clusterfile_ + ".c" + integerToString( cnum ); - // Set up trajectory file - Trajout_Single clusterout; - if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), clusterparm, - coords_->CoordsInfo(), C->Nframes(), - clusterfmt_)) - { - mprinterr("Error: Could not set up cluster trajectory %s for write.\n", - cfilename.c_str()); - return; - } - // Loop over all frames in cluster - int set = 0; - Frame clusterframe = coords_->AllocateFrame(); - for (ClusterNode::frame_iterator fnum = C->beginframe(); - fnum != C->endframe(); ++fnum) - { - coords_->GetFrame( *fnum, clusterframe ); - clusterout.WriteSingle(set++, clusterframe); - } - // Close traj - clusterout.EndTraj(); - } -} - -// Analysis_Clustering::WriteAvgStruct() -void Analysis_Clustering::WriteAvgStruct( ClusterList const& CList ) { - Topology avgparm = coords_->Top(); - // Get extension for representative frame format - std::string tmpExt = TrajectoryFile::WriteFormatExtension(avgfmt_); - // Loop over all clusters - for (ClusterList::cluster_iterator C = CList.begincluster(); - C != CList.endcluster(); ++C) - { - // Create filename based on cluster number. - int cnum = C->Num(); - std::string cfilename = avgfile_ + ".c" + integerToString( cnum ) + tmpExt; - // Set up trajectory file - Trajout_Single clusterout; // FIXME CoordinateInfo OK for just coords? - if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), &avgparm, - CoordinateInfo(), 1, avgfmt_)) - { - mprinterr("Error: Could not set up cluster average file %s for write.\n", - cfilename.c_str()); - return; - } - // Get rep frame for rms fitting. - Frame repframe = coords_->AllocateFrame(); - coords_->GetFrame( C->BestRepFrame(), repframe ); - Vec3 reftrans = repframe.CenterOnOrigin(false); - // Loop over all frames in cluster - Frame clusterframe = coords_->AllocateFrame(); - Frame avgframe = clusterframe; - avgframe.ZeroCoords(); - for (ClusterNode::frame_iterator fnum = C->beginframe(); - fnum != C->endframe(); ++fnum) - { - coords_->GetFrame( *fnum, clusterframe ); - clusterframe.RMSD_FitToRef( repframe, reftrans ); - avgframe += clusterframe; - } - avgframe.Divide( (double)C->Nframes() ); - clusterout.WriteSingle(0, avgframe); - clusterout.EndTraj(); - } -} - -// Analysis_Clustering::WriteSingleRepTraj() -/** Write representative frame of each cluster to a trajectory file. */ -void Analysis_Clustering::WriteSingleRepTraj( ClusterList const& CList ) { - Trajout_Single clusterout; - // Set up trajectory file. Use parm from COORDS DataSet. - Topology *clusterparm = coords_->TopPtr(); - if (clusterout.PrepareTrajWrite(singlerepfile_, ArgList(), DataSetList(), clusterparm, - coords_->CoordsInfo(), CList.Nclusters() * nRepsToSave_, - singlerepfmt_)) - { - mprinterr("Error: Could not set up single trajectory for represenatatives %s for write.\n", - singlerepfile_.c_str()); - return; - } - // Set up frame to hold cluster rep coords. - Frame clusterframe = coords_->AllocateFrame(); - int framecounter = 0; - // Write rep frames from all clusters. - for (ClusterList::cluster_iterator cluster = CList.begincluster(); - cluster != CList.endcluster(); ++cluster) - { - for (ClusterNode::RepPairArray::const_iterator rep = cluster->BestReps().begin(); - rep != cluster->BestReps().end(); ++rep) - { - coords_->GetFrame( rep->first, clusterframe ); - clusterout.WriteSingle(framecounter++, clusterframe); - } - } - // Close traj - clusterout.EndTraj(); -} - -// Analysis_Clustering::WriteRepTraj() -/** Write representative frame of each cluster to a separate trajectory file, - * repfile.REPNUM.FMT - */ -void Analysis_Clustering::WriteRepTraj( ClusterList const& CList ) { - // Get extension for representative frame format - std::string tmpExt = TrajectoryFile::WriteFormatExtension(reptrajfmt_); - // Use Topology from COORDS DataSet to set up input frame - Topology* clusterparm = coords_->TopPtr(); - Frame clusterframe = coords_->AllocateFrame(); - // Loop over all clusters - for (ClusterList::cluster_iterator C = CList.begincluster(); - C != CList.endcluster(); ++C) - { - if (writeRepFrameNum_) { - // Each rep from cluster to separate file. - for (ClusterNode::RepPairArray::const_iterator rep = C->BestReps().begin(); - rep != C->BestReps().end(); ++rep) - { - Trajout_Single clusterout; - // Get best rep frame # - int framenum = rep->first; - // Create filename based on cluster number and frame # - std::string cfilename = reptrajfile_ + ".c" + integerToString(C->Num()) + - ("." + integerToString(framenum+1)) + tmpExt; - // Set up trajectory file. - if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), clusterparm, - coords_->CoordsInfo(), 1, reptrajfmt_)) - { - mprinterr("Error: Could not set up representative trajectory file %s for write.\n", - cfilename.c_str()); - return; - } - // Write cluster rep frame - coords_->GetFrame( framenum, clusterframe ); - clusterout.WriteSingle(framenum, clusterframe); - // Close traj - clusterout.EndTraj(); - } - } else { - // Each rep from cluster to single file. - Trajout_Single clusterout; - // Create filename based on cluster number - std::string cfilename = reptrajfile_ + ".c" + integerToString(C->Num()) + tmpExt; - // Set up trajectory file. - if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), clusterparm, - coords_->CoordsInfo(), nRepsToSave_, reptrajfmt_)) - { - mprinterr("Error: Could not set up representative trajectory file %s for write.\n", - cfilename.c_str()); - return; - } - int framecounter = 0; - for (ClusterNode::RepPairArray::const_iterator rep = C->BestReps().begin(); - rep != C->BestReps().end(); ++rep) - { - // Write cluster rep frame - coords_->GetFrame( rep->first, clusterframe ); - clusterout.WriteSingle( framecounter++, clusterframe ); - } - // Close traj - clusterout.EndTraj(); - } - } -} diff --git a/src/Analysis_Clustering.h b/src/Analysis_Clustering.h index 979cb69b6d..e2a78a6e74 100644 --- a/src/Analysis_Clustering.h +++ b/src/Analysis_Clustering.h @@ -1,84 +1,19 @@ #ifndef INC_ANALYSIS_CLUSTERING_H #define INC_ANALYSIS_CLUSTERING_H #include "Analysis.h" -#include "ClusterList.h" -#include "TrajectoryFile.h" -#include "DataSet_Coords.h" -// Class: Analysis_Clustering -/// Used to perform clustering of frames, currently by RMSD only. -class Analysis_Clustering: public Analysis { +#include "Cluster/Control.h" +/// Perform cluster analysis on DataSets +class Analysis_Clustering : public Analysis { public: - Analysis_Clustering(); - ~Analysis_Clustering(); - + Analysis_Clustering() : masterDSL_(0) {} DispatchObject* Alloc() const { return (DispatchObject*)new Analysis_Clustering(); } void Help() const; + Analysis::RetType Setup(ArgList&, AnalysisSetup&, int); Analysis::RetType Analyze(); private: - inline void GetClusterTrajArgs(ArgList&, const char*, const char*, std::string&, - TrajectoryFile::TrajFormatType&) const; - void AssignRefsToClusters(ClusterList&) const; - void CreateCnumvtime( ClusterList const&, unsigned int ); - void CreateCpopvtime( ClusterList const&, unsigned int ); - void ClusterLifetimes( ClusterList const&, unsigned int ); - void NclustersObserved(ClusterList const&, unsigned int); - void WriteClusterTraj( ClusterList const& ); - void WriteAvgStruct( ClusterList const& ); - void WriteSingleRepTraj( ClusterList const& ); - void WriteRepTraj( ClusterList const& ); - - DataSetList* masterDSL_; ///< For Cluster pop v time DataSets. - DataSetList refs_; ///< Hold references for cluster name assignment. - DataSet_Coords* coords_; ///< Hold coordinates of frames being clustered. - ClusterList* CList_; ///< Hold specified clustering algorithm. - std::string maskexpr_; ///< If RMSD, Atoms to cluster on - std::string refmaskexpr_; ///< If assigning refs, atoms to calc RMSD to. - int sieve_; ///< If > 1, frames to skip on initial clustering pass. - int sieveSeed_; ///< Used to seed random number gen for sieve - int windowSize_; ///< Window size for # clusters seen vs time. - int drawGraph_; - int draw_maxit_; - int nRepsToSave_; ///< Number of best representative structures to save - double draw_tol_; - double refCut_; ///< RMSD cutoff for assigning reference names to clusters. - std::vector splitFrames_; ///< Frames to split at when comparing parts. - DataSet* cnumvtime_; ///< Cluster vs time dataset. - DataSet* clustersVtime_; ///< # clusters seen vs time dataset. - DataSet* pw_dist_; ///< Cluster pairwise distance matrix dataset - DataFile* cpopvtimefile_; ///< Cluster pop v time file. - DataFile* pwd_file_; ///< Data file to write pairwise distance matrix to. - // TODO use FileName - std::string summaryfile_; ///< Summary file name - std::string halffile_; ///< 1st/2nd half summary file name - std::string clusterfile_; ///< Cluster trajectory base filename. - std::string singlerepfile_; ///< Cluster all rep single trajectory filename. - std::string reptrajfile_; ///< Cluster rep to separate trajectory filename. - std::string avgfile_; ///< Cluster traj average structure filename. - std::string clusterinfo_; ///< Name for Ptraj-like cluster output file. - std::string sil_file_; ///< Prefix name of file for cluster silhouette. - bool nofitrms_; ///< If true do not best-fit when calc RMSD. - ClusterList::DistMetricType metric_; - bool useMass_; - bool grace_color_; ///< If true print grace colors instead of cluster number - enum normPopType { NONE=0, CLUSTERPOP, FRAME }; - normPopType norm_pop_; ///< If set cluster pops v time will be normalized - enum BestRepType { CUMULATIVE = 0, CENTROID, CUMULATIVE_NOSIEVE }; - BestRepType bestRep_; - bool calc_lifetimes_; ///< If true calculate DataSets for use in lifetime analysis. - bool writeRepFrameNum_; ///< If true frame #s will be in rep file names. - bool includeSieveInCalc_; ///< If true use sieved frames in certain calculations. - bool suppressInfo_; ///< If true, do not print cluster info to STDOUT - bool pw_mismatch_fatal_; ///< If true, existing PW matrix size must match expected size. - ClusterDist::DsArray cluster_dataset_; ///< DataSet(s) to use for clustering. - TrajectoryFile::TrajFormatType clusterfmt_; ///< Cluster trajectory format. - TrajectoryFile::TrajFormatType singlerepfmt_; ///< Cluster all rep single trajectory format. - TrajectoryFile::TrajFormatType reptrajfmt_; ///< Cluster rep to separate trajectory format. - TrajectoryFile::TrajFormatType avgfmt_; ///< Cluster traj average structure file format. - int debug_; + Cpptraj::Cluster::Control control_; - static const TrajectoryFile::TrajFormatType DEF_TRAJ_FMT_; - static const char* PAIRDISTFILE_; ///< Default pairwise dist file name. - static DataFile::DataFormatType PAIRDISTTYPE_; ///< Default pairwise dist file type. + DataSetList* masterDSL_; }; #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0c96cf167..6e3ced2082 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(xdrfile) +add_subdirectory(Cluster) #--------------------------------------------------------------------------------------------------------------------------------------------------------------------- # Parse cpptrajfiles @@ -18,32 +19,35 @@ foreach(LINE ${CPPTRAJFILES_CONTENTS}) if(NOT "${LINE}" MATCHES "^#") # extract the name of the source file mentioned in the line (a string after whitespace or an equals sign) - string(REGEX MATCH "[^ :=]+\.(cpp|c|LIBCPPTRAJ\.o)" SOURCE_FILE_NAME "${LINE}") - + string(REGEX MATCH "[^ :=]+\.(o|cpp|c|LIBCPPTRAJ\.o)" SOURCE_FILE_NAME "${LINE}") + # get name of variable that the following list is being set to # must exclude parentheses so that we don't match dereferences of other variables string(REGEX MATCH "[^$\(\)]+=" VARIABLE_NAME "${LINE}") - + # if we are starting a new source list, update LIST_NAME accordingly if(NOT "${VARIABLE_NAME}" STREQUAL "") string(REPLACE "=" "" VARIABLE_NAME "${VARIABLE_NAME}") set(LIST_NAME ${VARIABLE_NAME}) endif() - + # did we get a new source file? if(NOT "${SOURCE_FILE_NAME}" STREQUAL "") - + if("${LIST_NAME}" STREQUAL "") message(FATAL_ERROR "cpptrajfiles parser error: got source files before any source lists!") endif() - + # get rid of LIBCPPTRAJ.o suffix if it exists string(REPLACE "LIBCPPTRAJ.o" "cpp" SOURCE_FILE_NAME "${SOURCE_FILE_NAME}") + + # also convert .o to .cpp (used in some variables) + string(REPLACE ".o" ".cpp" SOURCE_FILE_NAME "${SOURCE_FILE_NAME}") - + list(APPEND ${LIST_NAME} ${SOURCE_FILE_NAME}) endif() - + #message("\"${LINE}\" - SFN: \"${SOURCE_FILE_NAME}\" - VN: \"${VARIABLE_NAME}\"") endif() endforeach() @@ -52,20 +56,35 @@ endforeach() # COMMON_SOURCES - all C++ source files used for both cpptraj and libcpptraj, that are compiled the same way for both # CSOURCES - all C source files used for cpptraj and libcpptraj # SOURCES - C++ sources for cpptraj only -# LIBCPPTRAJ_OBJECTS - C++ sources for libcpptraj that should be compiled with the LIBCPPTRAJ definition +# LIBCPPTRAJ_OBJECTS - C++ sources for libcpptraj that should be compiled with the LIBCPPTRAJ definition +# LIBCPPTRAJ_CORE_OBJECTS - C++ sources which contain "core" functionality. +# LIBCPPTRAJ_FILE_OBJECTS - C++ sources which contain basic file-related functionality. Requires core library +# LIBCPPTRAJ_TRAJ_OBJECTS - C++ sources which contain trajectory file functionality. Requires core and file libraries, as well as libxdrfile. +# LIBCPPTRAJ_PARM_OBJECTS - C++ sources which contain parameter file functionality. Requires core and file libraries. # pub_fft.F90 is not in the source lists set(PUBFFT_FORTRAN_SOURCE pub_fft.F90) #--------------------------------------------------------------------------------------------------------------------------------------------------------------------- +# with icc, cpptraj needs -fp-model source in order to produce floating point results that match gcc +set(FP_SOURCE_FLAG "") +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") + check_cxx_compiler_flag("-fp-model source" FP_MODEL_SOURCE_WORKS) + + if(FP_MODEL_SOURCE_WORKS) + set(FP_SOURCE_FLAG "-fp-model source") + endif() +endif() + +# all sources should use optimized compile flags set_property(SOURCE ${PUBFFT_FORTRAN_SOURCE} PROPERTY COMPILE_FLAGS "${OPT_FFLAGS_SPC}") -set_property(SOURCE ${COMMON_SOURCES} ${SOURCES} ${LIBCPPTRAJ_OBJECTS} PROPERTY COMPILE_FLAGS "${OPT_CXXFLAGS_SPC}") +set_property(SOURCE ${COMMON_SOURCES} ${SOURCES} ${LIBCPPTRAJ_OBJECTS} PROPERTY COMPILE_FLAGS "${OPT_CXXFLAGS_SPC} ${FP_SOURCE_FLAG}") set_property(SOURCE ${CSOURCES} PROPERTY COMPILE_FLAGS "${OPT_CFLAGS_SPC}") include_directories(${AMBERTOOLS_INC_DIR}) -if(fftw_ENABLED) +if(fftw_ENABLED) set_property(SOURCE PubFFT.cpp PROPERTY COMPILE_DEFINITIONS FFTW_FFT) endif() @@ -89,13 +108,13 @@ make_pic_if_needed(cpptraj_common_obj) # it turns out that CMake's cuda library passes the include paths after the first one from each of these generator expressions to nvcc without the -I flag # This causes the error "A single input file is required for a non-link phase when an outputfile is specified" target_include_directories(cpptraj_common_obj PRIVATE $ $) - + #--------------------------------------------------------------------------------------------------------------------------------------------------------------------- # cpptraj executable add_executable(cpptraj $ ${SOURCES}) -target_link_libraries(cpptraj netcdf netlib) +target_link_libraries(cpptraj cpptraj_cluster netcdf netlib xdrfile) install(TARGETS cpptraj DESTINATION ${BINDIR}) #------------------------------------------------------------------------------------------ @@ -104,13 +123,32 @@ install(TARGETS cpptraj DESTINATION ${BINDIR}) add_library(libcpptraj $ ${LIBCPPTRAJ_OBJECTS}) set_property(TARGET libcpptraj PROPERTY COMPILE_DEFINITIONS LIBCPPTRAJ) -target_link_libraries(libcpptraj netcdf netlib) +target_link_libraries(libcpptraj cpptraj_cluster netlib netcdf xdrfile) remove_prefix(libcpptraj) install_libraries(libcpptraj) #tell others where to find the cpptraj includes target_include_directories(libcpptraj INTERFACE .) +#------------------------------------------------------------------------------------------ +# Static libraries +# (not installed, used by other targets inside Amber which only need a subset of cpptraj functionality) +add_library(cpptraj_core STATIC ${LIBCPPTRAJ_CORE_OBJECTS}) +add_library(cpptraj_file STATIC ${LIBCPPTRAJ_FILE_OBJECTS}) +add_library(cpptraj_traj STATIC ${LIBCPPTRAJ_TRAJ_OBJECTS}) +add_library(cpptraj_parm STATIC ${LIBCPPTRAJ_PARM_OBJECTS}) + +# all libraries include the current dir as an interface directory +# FIXME DISABLED UNTIL CMAKE SUBMODULE UPDATED +#targets_include_directories(cpptraj_core cpptraj_file cpptraj_traj cpptraj_parm DIRECTORIES INTERFACE .) + +# cpptraj_traj needs xdrfile and netcdf +target_include_directories(cpptraj_traj PRIVATE $ $) +target_link_libraries(cpptraj_traj xdrfile netcdf) + +# all libs need netlib +targets_link_libraries(cpptraj_core cpptraj_file cpptraj_traj cpptraj_parm LIBRARIES netlib) + #------------------------------------------------------------------------------------------ # DLL exports/imports @@ -130,13 +168,13 @@ if(INSTALL_HEADERS) # grab all .h files from the main directory. file(GLOB CPPTRAJ_HEADERS "*.h") list(REMOVE_ITEM CPPTRAJ_HEADERS "SymbolExporting.h") - + # also grab xdrfile headers since some of them are used by cpptraj headers file(GLOB XDRFILE_HEADERS "xdrfile/*.h") install(FILES ${CPPTRAJ_HEADERS} DESTINATION ${INCDIR}/cpptraj) install(FILES ${XDRFILE_HEADERS} DESTINATION ${INCDIR}/cpptraj/xdrfile) - + # configure SymbolExporting.h specially for the current install type if(SHARED) set(CPPTRAJ_IS_SHARED 1) @@ -144,9 +182,9 @@ if(INSTALL_HEADERS) set(CPPTRAJ_IS_SHARED 0) endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/SymbolExporting-installversion.h.in ${CMAKE_CURRENT_BINARY_DIR}/SymbolExporting-installversion.h @ONLY) - + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/SymbolExporting-installversion.h DESTINATION ${INCDIR}/cpptraj RENAME SymbolExporting.h) - + endif() #--------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -159,17 +197,17 @@ endif() if(libbz2_ENABLED) add_definitions(-DHASBZ2) include_directories(${BZIP2_INCLUDE_DIR}) - targets_link_libraries(cpptraj libcpptraj LIBRARIES bzip2) + targets_link_libraries(cpptraj cpptraj_file libcpptraj LIBRARIES BZip2::BZip2) endif() if(zlib_ENABLED) add_definitions(-DHASGZ) include_directories(${ZLIB_INCLUDE_DIRS}) - targets_link_libraries(cpptraj libcpptraj LIBRARIES ${ZLIB_LIBRARIES}) + targets_link_libraries(cpptraj cpptraj_file libcpptraj LIBRARIES ZLIB::ZLIB) endif() if(fftw_ENABLED) - target_include_directories(cpptraj_common_obj PRIVATE $) + target_include_directories(cpptraj_common_obj PRIVATE $) targets_link_libraries(cpptraj libcpptraj LIBRARIES fftw) endif() @@ -181,8 +219,11 @@ else() target_compile_definitions(libcpptraj PRIVATE NO_READLINE) endif() -#xdrfile -targets_link_libraries(cpptraj libcpptraj LIBRARIES xdrfile) +if(tng_io_ENABLED) + add_definitions(-DHAS_TNGFILE) + include_directories($) + targets_link_libraries(cpptraj cpptraj_file libcpptraj LIBRARIES tng_io) +endif() # libsander if(INSIDE_AMBER AND ("${AMBER_TOOLS}" MATCHES "sander" AND BUILD_SANDER_API)) @@ -191,7 +232,6 @@ if(INSIDE_AMBER AND ("${AMBER_TOOLS}" MATCHES "sander" AND BUILD_SANDER_API)) target_link_libraries(cpptraj libsander) endif() - # arpack if(arpack_DISABLED) add_definitions(-DNO_ARPACK) @@ -205,13 +245,13 @@ if(MPI) make_mpi_version(cpptraj_common_obj cpptraj_common_obj_mpi LANGUAGES CXX) make_mpi_version(cpptraj cpptraj.MPI LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) make_mpi_version(libcpptraj libcpptraj_mpi LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) - + set_property(TARGET cpptraj.MPI libcpptraj_mpi cpptraj_common_obj_mpi APPEND PROPERTY COMPILE_DEFINITIONS MPI) # since we use CXX mpi, we have to define this manually - + if(pnetcdf_ENABLED) targets_link_libraries(cpptraj.MPI libcpptraj_mpi LIBRARIES pnetcdf) target_include_directories(cpptraj_common_obj_mpi PUBLIC $) - set_property(TARGET cpptraj.MPI libcpptraj_mpi cpptraj_common_obj_mpi APPEND PROPERTY COMPILE_DEFINITIONS HAS_PNETCDF) + set_property(TARGET cpptraj.MPI libcpptraj_mpi cpptraj_common_obj_mpi APPEND PROPERTY COMPILE_DEFINITIONS HAS_PNETCDF) endif() endif() @@ -226,43 +266,37 @@ if(BUILD_PARALLEL_COMBINATIONS AND (MPI AND OPENMP)) make_openmp_version(cpptraj.MPI cpptraj.MPI.OMP LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) make_openmp_version(libcpptraj_mpi libcpptraj_mpi_omp LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) endif() - + # CUDA if(CUDA) - if(HIP) - # TODO: Replace __HIP_PLATFORM_HCC__ after 4.1 rocm release - add_compile_definitions(__HIP_PLATFORM_HCC__) - add_compile_options(-fPIC) - include_directories(${CUDA_TOOLKIT_ROOT_DIR}/include) - endif() add_subdirectory(cuda_kernels) - + include_directories(${CUDA_INCLUDE_DIRS}) - + copy_target(cpptraj_common_obj cpptraj_common_obj_cuda) target_compile_definitions(cpptraj_common_obj_cuda PRIVATE CUDA) - + copy_target(cpptraj cpptraj.cuda SWAP_SOURCES $ TO $) copy_target(libcpptraj libcpptraj_cuda SWAP_SOURCES $ TO $) - + target_compile_definitions(cpptraj.cuda PRIVATE CUDA) target_compile_definitions(libcpptraj_cuda PRIVATE CUDA) - + targets_link_libraries(cpptraj.cuda libcpptraj_cuda LIBRARIES cpptraj_cuda_routines) - + install(TARGETS cpptraj.cuda DESTINATION ${BINDIR} COMPONENT CUDA) - + if(BUILD_PARALLEL_COMBINATIONS AND MPI) make_mpi_version(cpptraj_common_obj_cuda cpptraj_common_obj_mpi_cuda LANGUAGES CXX) make_mpi_version(cpptraj.cuda cpptraj.MPI.cuda LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) make_mpi_version(libcpptraj_cuda libcpptraj_mpi_cuda LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) - + set_property(TARGET cpptraj.MPI.cuda libcpptraj_mpi_cuda cpptraj_common_obj_mpi_cuda APPEND PROPERTY COMPILE_DEFINITIONS MPI) # since we use CXX mpi, we have to define this manually - + if(pnetcdf_ENABLED) targets_link_libraries(cpptraj.MPI.cuda libcpptraj_mpi_cuda LIBRARIES pnetcdf) target_include_directories(cpptraj_common_obj_mpi_cuda PUBLIC $) - set_property(TARGET cpptraj.MPI.cuda libcpptraj_mpi_cuda cpptraj_common_obj_mpi_cuda APPEND PROPERTY COMPILE_DEFINITIONS HAS_PNETCDF) + set_property(TARGET cpptraj.MPI.cuda libcpptraj_mpi_cuda cpptraj_common_obj_mpi_cuda APPEND PROPERTY COMPILE_DEFINITIONS HAS_PNETCDF) endif() endif() @@ -278,7 +312,9 @@ if(CUDA) make_openmp_version(cpptraj.MPI.cuda cpptraj.MPI.OMP.cuda LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) make_openmp_version(libcpptraj_mpi_cuda libcpptraj_mpi_omp_cuda LANGUAGES CXX SWAP_SOURCES $ TO $ INSTALL) endif() - - - + + + endif() + + diff --git a/src/Cluster/Algorithm.cpp b/src/Cluster/Algorithm.cpp new file mode 100644 index 0000000000..7d75a8c813 --- /dev/null +++ b/src/Cluster/Algorithm.cpp @@ -0,0 +1,17 @@ +#include "Algorithm.h" +#include "MetricArray.h" +#include "Node.h" +#include "../CpptrajStdio.h" + +/** \return Distance between given cluster centroids. */ +double Cpptraj::Cluster::Algorithm::ClusterDistance(Node const& C1, Node const& C2, + MetricArray& pmatrix, + bool includeSieved, + Cframes const& sievedOut) const +{ + if (C1.Cent().empty() || C2.Cent().empty()) { + mprinterr("Internal Error: One or both centroids are null in ClusterDistance().\n"); + return -1.0; + } + return pmatrix.CentroidDist( C1.Cent(), C2.Cent() ); +} diff --git a/src/Cluster/Algorithm.h b/src/Cluster/Algorithm.h new file mode 100644 index 0000000000..21297c997a --- /dev/null +++ b/src/Cluster/Algorithm.h @@ -0,0 +1,46 @@ +#ifndef INC_CLUSTER_ALGORITHM_H +#define INC_CLUSTER_ALGORITHM_H +class ArgList; +class CpptrajFile; +namespace Cpptraj { +namespace Cluster { +class Cframes; +class List; +class Node; +class MetricArray; +/// Abstract base class for implementing clustering algorithms. +class Algorithm { + public: + enum AType { HIERAGGLO = 0, DBSCAN, DPEAKS, KMEANS, UNSPECIFIED }; + + Algorithm(AType t) : debug_(0), type_(t) {} + virtual ~Algorithm() {} + /// Set up clustering algorithm + virtual int Setup(ArgList&) = 0; + /// Report details on algorithm setup. + virtual void Info() const = 0; + /// Report brief details on algorithm setup to a file. + virtual void Results(CpptrajFile&) const = 0; + /// Perform clustering on specified frames using given distance matrix. + virtual int DoClustering(List&, Cframes const&, MetricArray&) = 0; + /// Report any timing data + virtual void Timing(double) const = 0; + /// /return Algorithm-specific between-cluster distance. Default to centroid distance. + virtual double ClusterDistance(Node const&, Node const&, MetricArray&, + bool, Cframes const&) const; + /// /return Epsilon for density-based algorithms; intended for use with sieve restore. + virtual double Epsilon() const { return 0.0; } + // ------------------------------------------- + /// Set debug level for algorithm + void SetDebug(int d) { debug_ = d; } + /// \return Algorithm type + AType Type() const { return type_; } + protected: + int debug_; + private: + AType type_; +}; + +} /* END namespace Cluster */ +} /* END namespace Cpptraj */ +#endif diff --git a/src/Cluster_DBSCAN.cpp b/src/Cluster/Algorithm_DBscan.cpp similarity index 63% rename from src/Cluster_DBSCAN.cpp rename to src/Cluster/Algorithm_DBscan.cpp index 7cc1ae3dd1..853c3cf5ea 100644 --- a/src/Cluster_DBSCAN.cpp +++ b/src/Cluster/Algorithm_DBscan.cpp @@ -1,29 +1,35 @@ -#include // DBL_MAX +#include // double max #include // sort -#include "Cluster_DBSCAN.h" -#include "CpptrajStdio.h" -#include "ProgressBar.h" -#include "StringRoutines.h" // integerToString +#include "Algorithm_DBscan.h" +#include "Cframes.h" +#include "List.h" +#include "MetricArray.h" +#include "Node.h" +#include "../CpptrajStdio.h" +#include "../ArgList.h" +#include "../ProgressBar.h" +#include "../StringRoutines.h" // integerToString #ifdef _OPENMP # include #endif -#include "DataSet_MatrixDbl.h" // DEBUG -#include "DataFile.h" // DEBUG +#include "../DataSet_MatrixDbl.h" // DEBUG +#include "../DataFile.h" // DEBUG // CONSTRUCTOR -Cluster_DBSCAN::Cluster_DBSCAN() : +Cpptraj::Cluster::Algorithm_DBscan::Algorithm_DBscan() : + Algorithm(DBSCAN), minPoints_(-1), epsilon_(-1.0), sieveToCentroid_(true) {} -// Cluster_DBSCAN::Help() -void Cluster_DBSCAN::Help() { - mprintf("\t[dbscan minpoints epsilon [sievetoframe] [kdist [kfile ]]]\n"); +// Algorithm_DBscan::Help() +void Cpptraj::Cluster::Algorithm_DBscan::Help() { + mprintf("\t[dbscan minpoints epsilon [kdist [kfile ]]]\n"); } // Cluster_DBSCAN::SetupCluster() -int Cluster_DBSCAN::SetupCluster(ArgList& analyzeArgs) { +int Cpptraj::Cluster::Algorithm_DBscan::Setup(ArgList& analyzeArgs) { kdist_.SetRange(analyzeArgs.GetStringKey("kdist")); if (kdist_.Empty()) { minPoints_ = analyzeArgs.getKeyInt("minpoints", -1); @@ -38,7 +44,10 @@ int Cluster_DBSCAN::SetupCluster(ArgList& analyzeArgs) { "Error: Use 'epsilon '\n"); return 1; } - sieveToCentroid_ = !analyzeArgs.hasKey("sievetoframe"); + // NOTE: For backwards compatibility check if sievetoframe is here + // so it can be reported in info file, but do not mark + // it so that Control can pick it up. + sieveToCentroid_ = !analyzeArgs.Contains("sievetoframe"); } else { k_prefix_ = analyzeArgs.GetStringKey("kfile"); if (!k_prefix_.empty() && k_prefix_.at(k_prefix_.size()-1) != '/') @@ -48,7 +57,7 @@ int Cluster_DBSCAN::SetupCluster(ArgList& analyzeArgs) { } // Cluster_DBSCAN::ClusteringInfo() -void Cluster_DBSCAN::ClusteringInfo() const { +void Cpptraj::Cluster::Algorithm_DBscan::Info() const { mprintf("\tDBSCAN:\n"); if (!kdist_.Empty()) { mprintf("\t\tOnly calculating Kdist graph for K=%s\n", kdist_.RangeArg()); @@ -56,7 +65,7 @@ void Cluster_DBSCAN::ClusteringInfo() const { } else { mprintf("\t\tMinimum pts to form cluster= %i\n", minPoints_); mprintf("\t\tCluster distance criterion= %.3f\n", epsilon_); - if (sieveToCentroid_) +/* if (sieveToCentroid_) mprintf("\t\tSieved frames will be added back solely based on their\n" "\t\t closeness to cluster centroids.\n" "\t\t (This option is less accurate but faster.)\n"); @@ -64,29 +73,53 @@ void Cluster_DBSCAN::ClusteringInfo() const { mprintf("\t\tSieved frames will only be added back if they are within\n" "\t\t %.3f of a frame in an existing cluster.\n" "\t\t (This option is more accurate and will identify sieved\n" - "\t\t frames as noise but is slower.)\n", epsilon_); + "\t\t frames as noise but is slower.)\n", epsilon_);*/ } } -// Potential statuses if not in cluster -#define UNCLASSIFIED -2 -#define NOISE -1 - // Cluster_DBSCAN::Cluster() -int Cluster_DBSCAN::Cluster() { +int Cpptraj::Cluster::Algorithm_DBscan::DoClustering(List& clusters, + Cframes const& framesToCluster, + MetricArray& pmatrix) +{ // Check if only need to calculate Kdist function(s) if (!kdist_.Empty()) { if (kdist_.Size() == 1) - ComputeKdist( kdist_.Front(), FrameDistances().FramesToCluster() ); + ComputeKdist( kdist_.Front(), framesToCluster, pmatrix ); else - ComputeKdistMap( kdist_, FrameDistances().FramesToCluster() ); + ComputeKdistMap( kdist_, framesToCluster, pmatrix ); return 0; } // Actual clustering - unsigned int nPtsToCluster = FrameDistances().FramesToCluster().size(); + unsigned int nPtsToCluster = framesToCluster.size(); // SetOfPoints is UNCLASSIFIED Status_.assign( nPtsToCluster, UNCLASSIFIED ); int ClusterId = 0; + // If incoming clusters are not empty, set status of frames as appropriate. + if (!clusters.empty()) { + // Find highest cluster num + for (List::cluster_iterator node = clusters.begincluster(); + node != clusters.endcluster(); ++node) + if (node->Num() > ClusterId) ClusterId = node->Num(); + ClusterId++; + // See if any frames to be clustered are already in clusters. + for (Cframes::const_iterator it = framesToCluster.begin(); it != framesToCluster.end(); ++it) + { + for (List::cluster_iterator node = clusters.begincluster(); + node != clusters.endcluster(); ++node) + { + if (node->HasFrame( *it )) + Status_[it-framesToCluster.begin()] = node->Num(); + } + } + if (debug_ > 0) { + mprintf("DEBUG: Status based on existing clusters:\n"); + for (Iarray::const_iterator stat = Status_.begin(); stat != Status_.end(); ++stat) + mprintf("\t%10li %i\n", stat-Status_.begin(), *stat); + } + // Blow away existing clusters + clusters.Clear(); + } ProgressBar progress( nPtsToCluster ); for (unsigned int idx = 0; idx != nPtsToCluster; idx++) { @@ -96,34 +129,39 @@ int Cluster_DBSCAN::Cluster() { if ( Status_[idx] == UNCLASSIFIED ) { //IF ExpandCluster(SetOfPoints, Point, ClusterId, Eps, MinPts) THEN - if (ExpandCluster(idx, ClusterId)) + if (ExpandCluster(framesToCluster, pmatrix, idx, ClusterId)) //ClusterId := nextId(ClusterId) ClusterId++; } } // Create clusters based on point statuses if (ClusterId > 0) { - std::vector C0( ClusterId ); + std::vector C0( ClusterId ); + // Make sure to store actual frame #s for (unsigned int idx = 0; idx != Status_.size(); idx++) { int cnum = Status_[idx]; if (cnum == UNCLASSIFIED) mprintf("Warning: point %u was unclassified.\n", idx); - else if (cnum != NOISE) // Make sure to store actual frame #s - C0[ cnum ].push_back( FrameDistances().FramesToCluster()[idx] ); + else if (cnum == NOISE) + clusters.AddNoise( framesToCluster[idx] ); + else + C0[ cnum ].push_back( framesToCluster[idx] ); } // Add clusters. for (unsigned int cnum = 0; cnum != C0.size(); cnum++) - AddCluster( C0[cnum] ); + clusters.AddCluster( Node(pmatrix, C0[cnum], cnum) ); } return 0; } // Cluster_DBSCAN::ExpandCluster() -bool Cluster_DBSCAN::ExpandCluster(unsigned int point, int ClusterId) +bool Cpptraj::Cluster::Algorithm_DBscan::ExpandCluster(Cframes const& framesToCluster, + MetricArray& pmatrix, + unsigned int point, int ClusterId) { //seeds:=SetOfPoints.regionQuery(Point,Eps); - RegionQuery(seeds_, point); + RegionQuery(seeds_, framesToCluster, pmatrix, point); //IF seeds.size= MinPts THEN if ( (int)result_.size() >= minPoints_ ) { @@ -183,125 +221,38 @@ bool Cluster_DBSCAN::ExpandCluster(unsigned int point, int ClusterId) } // Cluster_DBSCAN::RegionQuery() -void Cluster_DBSCAN::RegionQuery(Iarray& NeighborPts, int point) const +void Cpptraj::Cluster::Algorithm_DBscan::RegionQuery(Iarray& NeighborPts, + Cframes const& framesToCluster, + MetricArray& pmatrix, + int point) const { NeighborPts.clear(); // point and otherpoint are indices, not frame #s - int f1 = FrameDistances().FramesToCluster()[ point ]; + int f1 = framesToCluster[ point ]; for (int otherpoint = 0; otherpoint < (int)Status_.size(); ++otherpoint) { if (point != otherpoint) { - int f2 = FrameDistances().FramesToCluster()[ otherpoint ]; - if ( FrameDistances().GetFdist(f1, f2) < epsilon_ ) + int f2 = framesToCluster[ otherpoint ]; + if ( pmatrix.Frame_Distance(f1, f2) < epsilon_ ) NeighborPts.push_back( otherpoint ); } } } // Cluster_DBSCAN::ClusterResults() -void Cluster_DBSCAN::ClusterResults(CpptrajFile& outfile) const { +void Cpptraj::Cluster::Algorithm_DBscan::Results(CpptrajFile& outfile) const { outfile.Printf("#Algorithm: DBSCAN minpoints %i epsilon %g sieveToCentroid %i\n", minPoints_, epsilon_, (int)sieveToCentroid_); - // List the number of noise points. - outfile.Printf("#NOISE_FRAMES:"); - unsigned int numNoise = 0; - for (unsigned int idx = 0; idx != Status_.size(); ++idx) - { - if ( Status_[idx] == NOISE ) { - outfile.Printf(" %u", FrameDistances().FramesToCluster()[idx]+1); - ++numNoise; - } - } - outfile.Printf("\n"); - outfile.Printf("#Number_of_noise_frames: %u\n", numNoise); -} - -// Cluster_DBSCAN::AddSievedFrames() -void Cluster_DBSCAN::AddSievedFrames() { - // NOTE: All cluster centroids must be up to date! - if (sieveToCentroid_) - mprintf("\tRestoring sieved frames if within %.3f of cluster centroid.\n", epsilon_); - else - mprintf("\tRestoring sieved frames if within %.3f of frame in nearest cluster.\n", - epsilon_); - // Vars allocated here in case of OpenMP - int n_sieved_noise = 0; - int Nsieved = 0; - int frame; - int nframes = (int)FrameDistances().OriginalNframes(); - ParallelProgress progress( nframes ); - // Need a temporary array to hold which frame belongs to which cluster. - // Otherwise we could be comparoing sieved frames to other sieved frames. - std::vector frameToCluster( nframes, clusters_.end() ); - // For OMP, every other thread will need its own Cdist. - ClusterDist* MyCdist = Cdist_; -# ifdef _OPENMP -# pragma omp parallel private(MyCdist, frame) firstprivate(progress) reduction(+ : Nsieved, n_sieved_noise) - { - int mythread = omp_get_thread_num(); - progress.SetThread( mythread ); - if (mythread == 0) { - mprintf("\tParallelizing calculation with %i threads\n", omp_get_num_threads()); - MyCdist = Cdist_; - } else - MyCdist = Cdist_->Copy(); -# pragma omp for schedule(dynamic) -# endif - for (frame = 0; frame < nframes; ++frame) { - progress.Update( frame ); - if (FrameDistances().FrameWasSieved(frame)) { - // Which clusters centroid is closest to this frame? - double mindist = DBL_MAX; - cluster_it minNode = clusters_.end(); - for (cluster_it Cnode = clusters_.begin(); Cnode != clusters_.end(); ++Cnode) { - double dist = MyCdist->FrameCentroidDist(frame, Cnode->Cent()); - if (dist < mindist) { - mindist = dist; - minNode = Cnode; - } - } - bool goodFrame = false; - if ( mindist < epsilon_ ) - // Frame is already within epsilon, accept. - goodFrame = true; - else if ( !sieveToCentroid_ ) { - // Check if any frames in the cluster are closer than epsilon to sieved frame. - for (int cidx=0; cidx < minNode->Nframes(); cidx++) - { - if ( MyCdist->FrameDist(frame, minNode->ClusterFrame(cidx)) < epsilon_ ) - { - goodFrame = true; - break; - } - } - } - // Add sieved frame to the closest cluster if closest distance is - // less than epsilon. - ++Nsieved; - if ( goodFrame ) - frameToCluster[frame] = minNode; - else - n_sieved_noise++; - } - } // END loop over frames -# ifdef _OPENMP - if (mythread > 0) - delete MyCdist; - } // END pragma omp parallel -# endif - progress.Finish(); - // Now actually add sieved frames to their appropriate clusters - for (frame = 0; frame < nframes; frame++) - if (frameToCluster[frame] != clusters_.end()) - frameToCluster[frame]->AddFrameToCluster( frame ); - mprintf("\t%i of %i sieved frames were discarded as noise.\n", - n_sieved_noise, Nsieved); } /** For each point p, calculate function Kdist(p) which is the distance of * the Kth nearest point to p. */ -void Cluster_DBSCAN::ComputeKdist( int Kval, std::vector const& FramesToCluster ) const { +void Cpptraj::Cluster::Algorithm_DBscan::ComputeKdist( int Kval, + Cframes const& FramesToCluster, + MetricArray& pmatrix ) +const +{ std::vector dists; std::vector Kdist; dists.reserve( FramesToCluster.size() ); @@ -317,7 +268,7 @@ void Cluster_DBSCAN::ComputeKdist( int Kval, std::vector const& FramesToClu for (std::vector::const_iterator otherpoint = FramesToCluster.begin(); otherpoint != FramesToCluster.end(); ++otherpoint) - dists.push_back( FrameDistances().GetFdist(*point, *otherpoint) ); + dists.push_back( pmatrix.Frame_Distance(*point, *otherpoint) ); // Sort distances - first dist should always be 0 std::sort(dists.begin(), dists.end()); Kdist.push_back( dists[Kval] ); @@ -335,8 +286,10 @@ void Cluster_DBSCAN::ComputeKdist( int Kval, std::vector const& FramesToClu } // Cluster_DBSCAN::ComputeKdistMap() -void Cluster_DBSCAN::ComputeKdistMap( Range const& Kvals, - std::vector const& FramesToCluster ) const +void Cpptraj::Cluster::Algorithm_DBscan::ComputeKdistMap( Range const& Kvals, + Cframes const& FramesToCluster, + MetricArray& pmatrix ) +const { int pt1_idx, pt2_idx, d_idx, point; mprintf("\tCalculating Kdist map for %s\n", Kvals.RangeArg()); @@ -372,7 +325,7 @@ void Cluster_DBSCAN::ComputeKdistMap( Range const& Kvals, d_idx = 0; // Store distances from pt1 to pt2 for (pt2_idx = 0; pt2_idx != nframes; pt2_idx++) - kdist_array[d_idx++] = FrameDistances().GetFdist(point, FramesToCluster[pt2_idx]); + kdist_array[d_idx++] = pmatrix.Frame_Distance(point, FramesToCluster[pt2_idx]); // Sort distances; will be smallest to largest std::sort( kdist_array, kdist_array + nframes ); // Save the distance of specified nearest neighbors to this point. diff --git a/src/Cluster_DBSCAN.h b/src/Cluster/Algorithm_DBscan.h similarity index 50% rename from src/Cluster_DBSCAN.h rename to src/Cluster/Algorithm_DBscan.h index 6cd9194853..ed5f263a09 100644 --- a/src/Cluster_DBSCAN.h +++ b/src/Cluster/Algorithm_DBscan.h @@ -1,28 +1,31 @@ -#ifndef INC_CLUSTER_DBSCAN_H -#define INC_CLUSTER_DBSCAN_H -#include "ClusterList.h" +#ifndef INC_CLUSTER_ALGORITHM_DBSCAN_H +#define INC_CLUSTER_ALGORITHM_DBSCAN_H +#include "Algorithm.h" +#include "../Range.h" +#include +namespace Cpptraj { +namespace Cluster { + /** Ester, Kriegel, Sander, Xu; Proceedings of 2nd International Conference * on Knowledge Discovery and Data Mining (KDD-96); pp 226-231. */ -class Cluster_DBSCAN : public ClusterList { +class Algorithm_DBscan : public Algorithm { public: - Cluster_DBSCAN(); + Algorithm_DBscan(); static void Help(); - int SetupCluster(ArgList&); - void ClusteringInfo() const; - int Cluster(); -# ifdef TIMER + int Setup(ArgList&); + void Info() const; + void Results(CpptrajFile&) const; + int DoClustering(List&, Cframes const&, MetricArray&); void Timing(double) const {} -# endif - void AddSievedFrames(); - void ClusterResults(CpptrajFile&) const; + double Epsilon() const { return epsilon_; } private: typedef std::vector Iarray; - bool ExpandCluster(unsigned int, int); - void RegionQuery(Iarray&, int) const; - void ComputeKdist( int, std::vector const& ) const ; - void ComputeKdistMap( Range const&, std::vector const& ) const ; + bool ExpandCluster(Cframes const&, MetricArray&, unsigned int, int); + void RegionQuery(Iarray&, Cframes const&, MetricArray&, int) const; + void ComputeKdist( int, Cframes const&, MetricArray&) const ; + void ComputeKdistMap( Range const&, Cframes const&, MetricArray& ) const ; Iarray Status_; ///< Status of each point: unclassified, noise, or in cluster Iarray seeds_; ///< Results from first RegionQuery @@ -33,4 +36,7 @@ class Cluster_DBSCAN : public ClusterList { std::string k_prefix_; ///< Kdist output file prefix. bool sieveToCentroid_; ///< If true sieve only based on closeness to centroid. }; + +} /* END namespace Cluster */ +} /* END namespace Cpptraj */ #endif diff --git a/src/Cluster_DPeaks.cpp b/src/Cluster/Algorithm_DPeaks.cpp similarity index 87% rename from src/Cluster_DPeaks.cpp rename to src/Cluster/Algorithm_DPeaks.cpp index 33ec99a9a4..5499fe5517 100644 --- a/src/Cluster_DPeaks.cpp +++ b/src/Cluster/Algorithm_DPeaks.cpp @@ -1,11 +1,17 @@ #include // fabs #include // sort -#include "Cluster_DPeaks.h" -#include "CpptrajStdio.h" -#include "DataSet_Mesh.h" -#include "ProgressBar.h" +#include "Algorithm_DPeaks.h" +#include "List.h" +#include "MetricArray.h" +#include "Node.h" +#include "../CpptrajStdio.h" +#include "../ArgList.h" +#include "../DataSet_Mesh.h" +#include "../ProgressBar.h" -Cluster_DPeaks::Cluster_DPeaks() : +/** CONSTRUCTOR */ +Cpptraj::Cluster::Algorithm_DPeaks::Algorithm_DPeaks() : + Algorithm(DPEAKS), densityCut_(-1.0), distanceCut_(-1.0), epsilon_(-1.0), @@ -13,14 +19,16 @@ Cluster_DPeaks::Cluster_DPeaks() : calc_noise_(false), useGaussianKernel_(false) {} -void Cluster_DPeaks::Help() { +/** Print help to STDOUT. */ +void Cpptraj::Cluster::Algorithm_DPeaks::Help() { mprintf("\t[dpeaks epsilon [noise] [dvdfile ]\n" - "\t [choosepoints {manual | auto}]\n" - "\t [distancecut ] [densitycut ]\n" - "\t [runavg ] [deltafile ] [gauss]]\n"); + "\t [choosepoints {manual | auto}]\n" + "\t [distancecut ] [densitycut ]\n" + "\t [runavg ] [deltafile ] [gauss]]\n"); } -int Cluster_DPeaks::SetupCluster(ArgList& analyzeArgs) { +/** Set up density peaks algorithm. */ +int Cpptraj::Cluster::Algorithm_DPeaks::Setup(ArgList& analyzeArgs) { epsilon_ = analyzeArgs.getKeyDouble("epsilon", -1.0); if (epsilon_ <= 0.0) { mprinterr("Error: DPeaks requires epsilon to be set and > 0.0\n" @@ -62,7 +70,8 @@ int Cluster_DPeaks::SetupCluster(ArgList& analyzeArgs) { return 0; } -void Cluster_DPeaks::ClusteringInfo() const { +/** Print dpeaks algorithm info. */ +void Cpptraj::Cluster::Algorithm_DPeaks::Info() const { mprintf("---------------------------------------------------------------------------\n" "Warning: The dpeaks algorithm is still under development. USE WITH CAUTION!\n" "---------------------------------------------------------------------------\n"); @@ -91,13 +100,17 @@ void Cluster_DPeaks::ClusteringInfo() const { mprintf("\t\tNo clustering, only writing density versus distance file.\n"); } -int Cluster_DPeaks::Cluster() { +/** Perform density peaks clustering. */ +int Cpptraj::Cluster::Algorithm_DPeaks::DoClustering(List& clusters, + Cframes const& framesToCluster, + MetricArray& pmatrix) +{ int err = 0; // Calculate local densities if ( useGaussianKernel_ ) - err = Cluster_GaussianKernel(); + err = Cluster_GaussianKernel(framesToCluster, pmatrix); else - err = Cluster_DiscreteDensity(); + err = Cluster_DiscreteDensity(framesToCluster, pmatrix); if (err != 0) return 1; // Choose points for which the min distance to point with higher density is // anomalously high. @@ -108,12 +121,19 @@ int Cluster_DPeaks::Cluster() { "Info: '%s'. Re-run the algorithm with appropriate distancecut and densitycut.\n", dvdfile_.c_str()); return 0; + } else if (clusters.Nclusters() > 0) { + nclusters = clusters.Nclusters(); + ChoosePointsFromClusters( clusters, framesToCluster ); } else if (choosePoints_ == MANUAL) nclusters = ChoosePointsManually(); else nclusters = ChoosePointsAutomatically(); mprintf("\tIdentified %i cluster centers from density vs distance peaks.\n", nclusters); + + // If no clusters found, no need to continue. + if (nclusters < 1) return 0; + // Each remaining point is assigned to the same cluster as its nearest // neighbor of higher density. Do this recursively until a cluster // center is found. @@ -167,7 +187,7 @@ int Cluster_DPeaks::Cluster() { for (unsigned int i1 = *idx1; i1 != *(idx1+1); i1++) { Cpoint const& other_point = Points_[i1]; - if (FrameDistances().GetFdist(point.Fnum(), other_point.Fnum()) < epsilon_) { + if (pmatrix.Frame_Distance(point.Fnum(), other_point.Fnum()) < epsilon_) { //mprintf("\tBorder frame: %i (to cluster %i frame %i)\n", // point.Fnum() + 1, c1, other_point.Fnum() + 1); borderIndices[c0].push_back( i0 ); @@ -215,31 +235,42 @@ int Cluster_DPeaks::Cluster() { } } } - } + // Ensure noise frames are sorted + std::vector noiseFrames; + for (Carray::const_iterator point = Points_.begin(); + point != Points_.end(); ++point) + if (point->Cnum() == -1) noiseFrames.push_back( point->Fnum() ); + std::sort( noiseFrames.begin(), noiseFrames.end() ); + for (std::vector::const_iterator f = noiseFrames.begin(); f != noiseFrames.end(); ++f) + clusters.AddNoise( *f ); + } // END noise calc // Add the clusters. for (Parray::const_iterator idx = C_start_stop.begin(); idx != C_start_stop.end(); idx += 2) { - ClusterDist::Cframes frames; + Cframes frames; for (unsigned int i = *idx; i != *(idx+1); i++) { if (Points_[i].Cnum() != -1) frames.push_back( Points_[i].Fnum() ); } if (!frames.empty()) - AddCluster( frames ); + clusters.AddCluster( Node(pmatrix, frames, clusters.Nclusters()) ); } return 0; } // ----------------------------------------------------------------------------- -int Cluster_DPeaks::Cluster_GaussianKernel() { +/** Gaussian kernel for density peaks. */ +int Cpptraj::Cluster::Algorithm_DPeaks::Cluster_GaussianKernel(Cframes const& framesToCluster, + MetricArray& pmatrix) +{ mprintf("\tStarting DPeaks clustering. Using Gaussian kernel to calculate density.\n"); // First determine which frames are being clustered. Points_.clear(); int oidx = 0; - for (int frame = 0; frame < (int)FrameDistances().OriginalNframes(); ++frame) - if (!FrameDistances().FrameWasSieved( frame )) - Points_.push_back( Cpoint(frame, oidx++) ); + for (Cframes::const_iterator frame = framesToCluster.begin(); + frame != framesToCluster.end(); ++frame) + Points_.push_back( Cpoint(*frame, oidx++) ); // Sanity check. if (Points_.size() < 2) { mprinterr("Error: Only 1 frame in initial clustering.\n"); @@ -248,9 +279,11 @@ int Cluster_DPeaks::Cluster_GaussianKernel() { // Sort distances std::vector Distances; - Distances.reserve( FrameDistances().Nelements() ); - for (unsigned int idx = 0; idx != FrameDistances().Nelements(); idx++) - Distances.push_back( FrameDistances().GetElement(idx) ); + unsigned int n_distances = (framesToCluster.size() * (framesToCluster.size()-1)) / 2; + Distances.reserve( n_distances ); + for (Cframes::const_iterator f1 = framesToCluster.begin(); f1 != framesToCluster.end(); ++f1) + for (Cframes::const_iterator f2 = f1 + 1; f2 != framesToCluster.end(); ++f2) + Distances.push_back( pmatrix.Frame_Distance( *f1, *f2 ) ); std::sort( Distances.begin(), Distances.end() ); unsigned int idx = (unsigned int)((double)Distances.size() * 0.02); double bandwidth = (double)Distances[idx]; @@ -260,7 +293,7 @@ int Cluster_DPeaks::Cluster_GaussianKernel() { double maxDist = -1.0; for (unsigned int i = 0; i != Points_.size(); i++) { for (unsigned int j = i+1; j != Points_.size(); j++) { - double dist = FrameDistances().GetFdist(Points_[i].Fnum(), Points_[j].Fnum()); + double dist = pmatrix.Frame_Distance(Points_[i].Fnum(), Points_[j].Fnum()); maxDist = std::max( maxDist, dist ); dist /= bandwidth; double gk = exp(-(dist *dist)); @@ -293,7 +326,7 @@ int Cluster_DPeaks::Cluster_GaussianKernel() { Points_[ord_i].SetDist( maxDist ); for (unsigned int jj = 0; jj != ii; jj++) { int ord_j = Points_[jj].Oidx(); - double dist = FrameDistances().GetFdist(Points_[ord_i].Fnum(), Points_[ord_j].Fnum()); + double dist = pmatrix.Frame_Distance(Points_[ord_i].Fnum(), Points_[ord_j].Fnum()); if (dist < Points_[ord_i].Dist()) { Points_[ord_i].SetDist( dist ); Points_[ord_j].SetNearestIdx( ord_j ); @@ -312,13 +345,16 @@ int Cluster_DPeaks::Cluster_GaussianKernel() { } // ----------------------------------------------------------------------------- -int Cluster_DPeaks::Cluster_DiscreteDensity() { +/** Discrete density. */ +int Cpptraj::Cluster::Algorithm_DPeaks::Cluster_DiscreteDensity(Cframes const& framesToCluster, + MetricArray& pmatrix) +{ mprintf("\tStarting DPeaks clustering, discrete density calculation.\n"); Points_.clear(); // First determine which frames are being clustered. - for (int frame = 0; frame < (int)FrameDistances().OriginalNframes(); ++frame) - if (!FrameDistances().FrameWasSieved( frame )) - Points_.push_back( Cpoint(frame) ); + for (Cframes::const_iterator frame = framesToCluster.begin(); + frame != framesToCluster.end(); ++frame) + Points_.push_back( Cpoint(*frame) ); // Sanity check. if (Points_.size() < 2) { mprinterr("Error: Only 1 frame in initial clustering.\n"); @@ -338,7 +374,7 @@ int Cluster_DPeaks::Cluster_DiscreteDensity() { point1 != Points_.end(); ++point1) { if (point0 != point1) { - double dist = FrameDistances().GetFdist(point0->Fnum(), point1->Fnum()); + double dist = pmatrix.Frame_Distance(point0->Fnum(), point1->Fnum()); maxDist = std::max(maxDist, dist); if ( dist < epsilon_ ) density++; @@ -375,7 +411,7 @@ int Cluster_DPeaks::Cluster_DiscreteDensity() { for (unsigned int idx1 = idx0+1; idx1 != Points_.size(); idx1++) { Cpoint const& point1 = Points_[idx1]; - double dist1_2 = FrameDistances().GetFdist(point0.Fnum(), point1.Fnum()); + double dist1_2 = pmatrix.Frame_Distance(point0.Fnum(), point1.Fnum()); if (point1.PointsWithinEps() > point0.PointsWithinEps()) { if (dist1_2 < min_dist) { @@ -411,7 +447,22 @@ int Cluster_DPeaks::Cluster_DiscreteDensity() { return 0; } -int Cluster_DPeaks::ChoosePointsManually() { +/** Choose points from clusters. */ +int Cpptraj::Cluster::Algorithm_DPeaks::ChoosePointsFromClusters(List const& clusters, + Cframes const& framesToCluster) +{ + for (List::cluster_iterator C = clusters.begincluster(); C != clusters.endcluster(); ++C) + for (Node::frame_iterator frm = C->beginframe(); frm != C->endframe(); ++frm) + { + int idx = framesToCluster.FrameIdx( *frm ); + if (idx != -1) + Points_[idx].SetCluster( C->Num() ); + } + return 0; +} + +/** Choose points based on user specified cutoffs. */ +int Cpptraj::Cluster::Algorithm_DPeaks::ChoosePointsManually() { int cnum = 0; for (Carray::iterator point = Points_.begin(); point != Points_.end(); ++point) { double density; @@ -428,7 +479,7 @@ int Cluster_DPeaks::ChoosePointsManually() { return cnum; } -int Cluster_DPeaks::ChoosePointsAutomatically() { +int Cpptraj::Cluster::Algorithm_DPeaks::ChoosePointsAutomatically() { // Right now all density values are discrete. Try to choose outliers at each // value for which there is density.; /* @@ -812,13 +863,13 @@ int Cluster_DPeaks::ChoosePointsAutomatically() { /** This should never be called for the point with highest density * which by definition should be a cluster center. */ -void Cluster_DPeaks::AssignClusterNum(int idx, int& cnum) { +void Cpptraj::Cluster::Algorithm_DPeaks::AssignClusterNum(int idx, int& cnum) { // Who is the nearest neighbor with higher density. int neighbor_idx = Points_[idx].NearestIdx(); //mprintf("Index %i nearest neighbor index %i\n", idx, neighbor_idx); // SANITY CHECK if (neighbor_idx == -1) { - mprinterr("Internal Error: In Cluster_DPeaks::AssignClusterNum nearest neighbor is -1.\n"); + mprinterr("Internal Error: In Algorithm_DPeaks::AssignClusterNum nearest neighbor is -1.\n"); return; } if (Points_[neighbor_idx].Cnum() != -1) { @@ -831,29 +882,14 @@ void Cluster_DPeaks::AssignClusterNum(int idx, int& cnum) { //mprintf("Index %i cnum %i\n", idx, cnum); // At this point cnum should be set. One more sanity check. if (cnum == -1) { - mprinterr("Internal Error: In Cluster_DPeaks::AssignClusterNum could not get" + mprinterr("Internal Error: In Algorithm_DPeaks::AssignClusterNum could not get" " cluster num for index %u.\n", idx); return; } Points_[idx].SetCluster( cnum ); } -void Cluster_DPeaks::ClusterResults(CpptrajFile& outfile) const { +/** Write results to file. */ +void Cpptraj::Cluster::Algorithm_DPeaks::Results(CpptrajFile& outfile) const { outfile.Printf("#Algorithm: DPeaks epsilon %g\n", epsilon_); - if (calc_noise_) { - outfile.Printf("#NOISE_FRAMES:"); - std::vector noiseFrames; - for (Carray::const_iterator point = Points_.begin(); - point != Points_.end(); ++point) - if (point->Cnum() == -1) noiseFrames.push_back( point->Fnum()+1 ); - std::sort( noiseFrames.begin(), noiseFrames.end() ); - for (std::vector::const_iterator f = noiseFrames.begin(); f != noiseFrames.end(); ++f) - outfile.Printf(" %i", *f); - outfile.Printf("\n"); - outfile.Printf("#Number_of_noise_frames: %zu\n", noiseFrames.size()); - } -} - -void Cluster_DPeaks::AddSievedFrames() { - mprintf("FIXME: Adding sieved frames not yet supported.\n"); } diff --git a/src/Cluster_DPeaks.h b/src/Cluster/Algorithm_DPeaks.h similarity index 83% rename from src/Cluster_DPeaks.h rename to src/Cluster/Algorithm_DPeaks.h index e711af3dcc..211bce174f 100644 --- a/src/Cluster_DPeaks.h +++ b/src/Cluster/Algorithm_DPeaks.h @@ -1,24 +1,29 @@ -#ifndef INC_CLUSTER_DPEAKS_H -#define INC_CLUSTER_DPEAKS_H -#include "ClusterList.h" -class Cluster_DPeaks : public ClusterList { +#ifndef INC_CLUSTER_ALGORITHM_DPEAKS_H +#define INC_CLUSTER_ALGORITHM_DPEAKS_H +#include "Algorithm.h" +#include +#include +namespace Cpptraj { +namespace Cluster { + +/// Implement density peaks clustering algorithm +class Algorithm_DPeaks : public Algorithm { public: - Cluster_DPeaks(); + Algorithm_DPeaks(); static void Help(); - int SetupCluster(ArgList&); - void ClusteringInfo() const; - int Cluster(); -# ifdef TIMER + int Setup(ArgList&); + void Info() const; + void Results(CpptrajFile&) const; + int DoClustering(List&, Cframes const&, MetricArray&); void Timing(double) const {} -# endif - void AddSievedFrames(); - void ClusterResults(CpptrajFile&) const; + double Epsilon() const { return epsilon_; } private: void AssignClusterNum(int, int&); - int Cluster_GaussianKernel(); - int Cluster_DiscreteDensity(); + int Cluster_GaussianKernel(Cframes const&, MetricArray&); + int Cluster_DiscreteDensity(Cframes const&, MetricArray&); int ChoosePointsAutomatically(); int ChoosePointsManually(); + int ChoosePointsFromClusters(List const&, Cframes const&); enum ChooseType {PLOT_ONLY = 0, MANUAL, AUTOMATIC}; std::string dvdfile_; @@ -31,6 +36,7 @@ class Cluster_DPeaks : public ClusterList { int avg_factor_; bool calc_noise_; bool useGaussianKernel_; + // ------------------------------------------- class Cpoint { public: Cpoint() : @@ -106,7 +112,11 @@ class Cluster_DPeaks : public ClusterList { int oidx_; ///< Original index in Carray before sorting. int cnum_; ///< Cluster number. -1 is no cluster. }; + // ------------------------------------------- typedef std::vector Carray; Carray Points_; ///< Hold info for each point to be clustered. }; + +} +} #endif diff --git a/src/Cluster/Algorithm_HierAgglo.cpp b/src/Cluster/Algorithm_HierAgglo.cpp new file mode 100644 index 0000000000..6ea0c39e6c --- /dev/null +++ b/src/Cluster/Algorithm_HierAgglo.cpp @@ -0,0 +1,399 @@ +#include // double max +#include "Algorithm_HierAgglo.h" +#include "MetricArray.h" +#include "Node.h" +#include "../CpptrajStdio.h" +#include "../ArgList.h" +#include "../ProgressBar.h" + +/** CONSTRUCTOR */ +Cpptraj::Cluster::Algorithm_HierAgglo::Algorithm_HierAgglo() : + Algorithm(HIERAGGLO), + nclusters_(-1), + epsilon_(-1.0), + linkage_(AVERAGELINK) +{} + +/** Print keywords to STDOUT */ +void Cpptraj::Cluster::Algorithm_HierAgglo::Help() { + mprintf("\t[hieragglo [epsilon ] [clusters ] [linkage|averagelinkage|complete]\n" + "\t [epsilonplot ]]\n"); +} + +/** Process user args */ +int Cpptraj::Cluster::Algorithm_HierAgglo::Setup(ArgList& analyzeArgs) { + nclusters_ = analyzeArgs.getKeyInt("clusters", -1); + epsilon_ = analyzeArgs.getKeyDouble("epsilon", -1.0); + if (analyzeArgs.hasKey("linkage")) linkage_ = SINGLELINK; + else if (analyzeArgs.hasKey("averagelinkage")) linkage_ = AVERAGELINK; + else if (analyzeArgs.hasKey("complete")) linkage_ = COMPLETELINK; + else linkage_ = AVERAGELINK; // DEFAULT linkage + std::string epsilonPlot = analyzeArgs.GetStringKey("epsilonplot"); + if (!epsilonPlot.empty()) { + if (eps_v_n_.OpenWrite( epsilonPlot )) return 1; + eps_v_n_.Printf("%-12s %12s\n", "#Epsilon", "Nclusters"); + } + // Determine finish criteria. If nothing specified default to 10 clusters. + if (nclusters_==-1 && epsilon_==-1.0) { + mprintf("Warning: cluster: Neither target # of clusters nor epsilon given.\n"); + nclusters_ = 10; + mprintf("Warning: cluster: Defaulting to %i clusters.\n", nclusters_); + } + return 0; +} + +/** Strings corresponding to LINKAGETYPE */ +const char* Cpptraj::Cluster::Algorithm_HierAgglo::LinkageString_[] = { + "single-linkage", "average-linkage", "complete-linkage" +}; + +/** Print info */ +void Cpptraj::Cluster::Algorithm_HierAgglo::Info() const { + mprintf("\tHierarchical Agglomerative:"); + if (nclusters_ != -1) + mprintf(" %i clusters,",nclusters_); + if (epsilon_ != -1.0) + mprintf(" epsilon %.3f,",epsilon_); + mprintf(" %s.\n", LinkageString_[linkage_]); + if (eps_v_n_.IsOpen()) + mprintf("\tWriting epsilon vs # clusters to '%s'\n", eps_v_n_.Filename().full()); +} + +/** Write info on clustering to info file. */ +void Cpptraj::Cluster::Algorithm_HierAgglo::Results(CpptrajFile& outfile) const { + outfile.Printf("#Algorithm: HierAgglo linkage %s nclusters %i epsilon %g\n", + LinkageString_[linkage_], nclusters_, epsilon_); +} + +/** Print clustering timing. */ +void Cpptraj::Cluster::Algorithm_HierAgglo::Timing(double total) const { +# ifdef TIMER + time_findMin_.WriteTiming(2, "Find min distance", total); + time_mergeFrames_.WriteTiming(2, "Merge cluster frames", total); + time_calcLinkage_.WriteTiming(2, "Calculate new linkage", total); +# endif +} + +/** Default: put all frames in their own starting cluster. */ +void Cpptraj::Cluster::Algorithm_HierAgglo::buildInitialClusters(List& clusters, + Cframes const& framesToCluster, + MetricArray& metric) +{ + int num = 0; + for (Cframes_it frm = framesToCluster.begin(); frm != framesToCluster.end(); ++frm) + { + Cframes oneframe(1, *frm); + clusters.AddCluster( Node(metric, oneframe, num++) ); + } +} + +/** Cluster using a hierarchical agglomerative (bottom-up) approach. All frames + * start in their own cluster. The closest two clusters are merged, and + * distances between the newly merged cluster and all remaining clusters are + * recalculated according to one of the following metrics: + * - single-linkage : The minimum distance between frames in clusters are used. + * - average-linkage : The average distance between frames in clusters are used. + * - complete-linkage: The maximum distance between frames in clusters are used. + */ +int Cpptraj::Cluster::Algorithm_HierAgglo::DoClustering(List& clusters, + Cframes const& framesToCluster, + MetricArray& pmatrix) +{ + // If epsilon not given make it huge + if (epsilon_ == -1.0) epsilon_ = std::numeric_limits::max(); + // If target clusters not given make it 1 + if (nclusters_ == -1) nclusters_ = 1; + mprintf("\tStarting Hierarchical Agglomerative Clustering:\n"); + ProgressBar cluster_progress(-10); + // Build initial clusters. + if (clusters.empty()) + buildInitialClusters(clusters, framesToCluster, pmatrix); + else if (clusters.Nclusters() <= nclusters_) { + mprintf("\tTarget number of clusters (%i) already reached (%i).\n", + nclusters_, clusters.Nclusters()); + return 0; + } + mprintf("\t%i initial clusters.\n", clusters.Nclusters()); + // Build initial cluster distance matrix. + ClusterDistances_.SetupMatrix( clusters.Nclusters() ); + double dval = -1.0; + for (List::cluster_it C1_it = clusters.begin(); C1_it != clusters.end(); C1_it++) + { + List::cluster_it C2_it = C1_it; + C2_it++; + for(; C2_it != clusters.end(); C2_it++) + { + switch (linkage_) { + case SINGLELINK : dval = minDist(*C1_it, *C2_it, pmatrix); break; + case COMPLETELINK : dval = maxDist(*C1_it, *C2_it, pmatrix); break; + case AVERAGELINK : dval = avgDist(*C1_it, *C2_it, pmatrix); break; + } + ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), dval ); + } + } + //InitializeClusterDistances(); + // DEBUG - print initial clusters + if (debug_ > 1) + clusters.PrintClusters(); + bool clusteringComplete = false; + int iterations = 0; + while (!clusteringComplete) { + // Merge 2 closest clusters. Clustering complete if closest dist > epsilon. + if (MergeClosest(clusters, pmatrix)) break; + // If the target number of clusters is reached we are done + if (clusters.Nclusters() <= nclusters_) { + mprintf("\n\tTarget # of clusters (%i) met (%u), clustering complete.\n", nclusters_, + clusters.Nclusters()); + break; + } + if (clusters.Nclusters() == 1) clusteringComplete = true; // Sanity check + cluster_progress.Update( iterations++ ); + } + mprintf("\tCompleted after %i iterations, %u clusters.\n",iterations, + clusters.Nclusters()); + return 0; +} + +/** Find and merge the two closest clusters. + * \return 1 if clustering is complete, 0 otherwise. + */ +int Cpptraj::Cluster::Algorithm_HierAgglo::MergeClosest(List& clusters, MetricArray& pmatrix) +{ + int C1, C2; + // Find the minimum distance between clusters. C1 will be lower than C2. +# ifdef TIMER + time_findMin_.Start(); +# endif + double min = ClusterDistances_.FindMin(C1, C2); +# ifdef TIMER + time_findMin_.Stop(); +# endif + if (eps_v_n_.IsOpen()) + eps_v_n_.Printf("%12g %12i\n", min, clusters.Nclusters()); + if (debug_>0) + mprintf("\tMinimum found between clusters %i and %i (%f)\n",C1,C2,min); + // If the minimum distance is greater than epsilon we are done + if (min > epsilon_) { + mprintf("\n\tMinimum distance (%f) is greater than epsilon (%f), clustering complete.\n", + min, epsilon_); + return 1; + } + + // Find C1, the number of the cluster to be merged into. + List::cluster_it C1_it = clusters.begin(); + for (; C1_it != clusters.end(); ++C1_it) + { + if ( C1_it->Num() == C1 ) break; + } + if (C1_it == clusters.end()) { + mprinterr("Error: MergeClosest: C1 (%i) not found.\n",C1); + return 1; + } + // Find C2 - start from C1 since C1 < C2 + List::cluster_it C2_it = C1_it; + for (; C2_it != clusters.end(); ++C2_it) { + if ( C2_it->Num() == C2 ) break; + } + if (C2_it == clusters.end()) { + mprinterr("Error: MergeClosest: C2 (%i) not found.\n",C2); + return 1; + } + + // Merge the closest clusters, C2 -> C1, remove C2 +# ifdef TIMER + time_mergeFrames_.Start(); +# endif + C1_it->MergeFrames( *C2_it ); + clusters.RemoveCluster( C2_it ); +# ifdef TIMER + time_mergeFrames_.Stop(); +# endif + // DEBUG + if (debug_>1) { + mprintf("\nAFTER MERGE of %i and %i:\n",C1,C2); + clusters.PrintClusters(); + } + // Remove all distances having to do with C2 + ClusterDistances_.Ignore(C2); +# ifdef TIMER + time_calcLinkage_.Start(); +# endif + switch (linkage_) { + case AVERAGELINK : calcAvgDist(C1_it, clusters, pmatrix); break; + case SINGLELINK : calcMinDist(C1_it, clusters, pmatrix); break; + case COMPLETELINK: calcMaxDist(C1_it, clusters, pmatrix); break; + } +# ifdef TIMER + time_calcLinkage_.Stop(); +# endif + if (debug_>2) { + mprintf("NEW CLUSTER DISTANCES:\n"); + ClusterDistances_.PrintElements(); + } + + return 0; +} + +/** \return The shortest distance between any two points in C1 and C2. */ +double Cpptraj::Cluster::Algorithm_HierAgglo::minDist(Node const& C1, + Node const& C2, + MetricArray& pmatrix) +{ + double min = std::numeric_limits::max(); + for (Node::frame_iterator c1frames = C1.beginframe(); c1frames != C1.endframe(); ++c1frames) + { + for (Node::frame_iterator c2frames = C2.beginframe(); c2frames != C2.endframe(); ++c2frames) + { + double Dist = pmatrix.Frame_Distance(*c1frames, *c2frames); + //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); + if ( Dist < min ) min = Dist; + } + } + return min; +} + +/** \return The longest distance between any two points in C1 and C2. */ +double Cpptraj::Cluster::Algorithm_HierAgglo::maxDist(Node const& C1, + Node const& C2, + MetricArray& pmatrix) +{ + double max = -1.0; + for (Node::frame_iterator c1frames = C1.beginframe(); c1frames != C1.endframe(); ++c1frames) + { + for (Node::frame_iterator c2frames = C2.beginframe(); c2frames != C2.endframe(); ++c2frames) + { + double Dist = pmatrix.Frame_Distance(*c1frames, *c2frames); + //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); + if ( Dist > max ) max = Dist; + } + } + return max; +} + +/** \return The average distance between points in C1 and C2. */ +double Cpptraj::Cluster::Algorithm_HierAgglo::avgDist(Node const& C1, + Node const& C2, + MetricArray& pmatrix) +{ + double sum = 0.0; + for (Node::frame_iterator c1frames = C1.beginframe(); c1frames != C1.endframe(); ++c1frames) + { + for (Node::frame_iterator c2frames = C2.beginframe(); c2frames != C2.endframe(); ++c2frames) + { + double Dist = pmatrix.Frame_Distance(*c1frames, *c2frames); + //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); + sum += Dist; + } + } + return sum / (double)(C1.Nframes() * C2.Nframes()); +} + +/** Calculate the minimum distance between frames in cluster specified by + * iterator C1 and frames in all other clusters. + */ +void Cpptraj::Cluster::Algorithm_HierAgglo::calcMinDist(List::cluster_it& C1_it, List& clusters, + MetricArray& pmatrix) +{ + // All cluster distances to C1 must be recalcd. + for (List::cluster_it C2_it = clusters.begin(); + C2_it != clusters.end(); ++C2_it) + { + if (C2_it != C1_it) { + double min = minDist(*C1_it, *C2_it, pmatrix); + //mprintf("\t\tMin distance between %i and %i: %f\n",C1,newc2,min); + ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), min ); + } + } +} + +/** Calculate the maximum distance between frames in cluster specified by + * iterator C1 and frames in all other clusters. + */ +void Cpptraj::Cluster::Algorithm_HierAgglo::calcMaxDist(List::cluster_it& C1_it, List& clusters, + MetricArray& pmatrix) +{ + // All cluster distances to C1 must be recalcd. + for (List::cluster_it C2_it = clusters.begin(); + C2_it != clusters.end(); ++C2_it) + { + if (C2_it != C1_it) { + double max = maxDist( *C1_it, *C2_it, pmatrix ); + //mprintf("\t\tMax distance between %i and %i: %f\n",C1,newc2,max); + ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), max ); + } + } +} + +/** Calculate the average distance between frames in cluster specified by + * iterator C1 and frames in all other clusters. + */ +void Cpptraj::Cluster::Algorithm_HierAgglo::calcAvgDist(List::cluster_it& C1_it, List& clusters, + MetricArray& pmatrix) +{ + // All cluster distances to C1 must be recalcd. + for (List::cluster_it C2_it = clusters.begin(); + C2_it != clusters.end(); ++C2_it) + { + if (C2_it != C1_it) { + double Dist = avgDist( *C1_it, *C2_it, pmatrix ); + //mprintf("\t\tAvg distance between %i and %i: %f\n",(*C1_it).Num(),(*C2_it).Num(),Dist); + ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), Dist ); + } + } +} + +/** \return the Distance between the two given cluster Nodes. */ +double Cpptraj::Cluster::Algorithm_HierAgglo::ClusterDistance(Node const& C1, Node const& C2, + MetricArray& pmatrix, + bool includeSieved, + Cframes const& sievedOut) +const +{ + double dval = -1.0; + switch (linkage_) { + case SINGLELINK : dval = std::numeric_limits::max(); break; + case COMPLETELINK : dval = -1.0; break; + case AVERAGELINK : dval = 0.0; break; + } + unsigned int nvals = 0; + + if (includeSieved) { + // Include sieved frames + for (Node::frame_iterator f1 = C1.beginframe(); f1 != C1.endframe(); ++f1) + { + for (Node::frame_iterator f2 = C2.beginframe(); f2 != C2.endframe(); ++f2) + { + double Dist = pmatrix.Frame_Distance(*f1, *f2); + //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); + switch (linkage_) { + case SINGLELINK : if ( Dist < dval ) dval = Dist; break; + case COMPLETELINK : if ( Dist > dval ) dval = Dist; break; + case AVERAGELINK : dval += Dist; nvals++; break; + } + } + } + } else { + // No sieved frames included. + for (Node::frame_iterator f1 = C1.beginframe(); f1 != C1.endframe(); ++f1) + { + if (!sievedOut.HasFrame(*f1)) { + for (Node::frame_iterator f2 = C2.beginframe(); f2 != C2.endframe(); ++f2) + { + if (!sievedOut.HasFrame(*f2)) { + double Dist = pmatrix.Frame_Distance(*f1, *f2); + //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); + switch (linkage_) { + case SINGLELINK : if ( Dist < dval ) dval = Dist; break; + case COMPLETELINK : if ( Dist > dval ) dval = Dist; break; + case AVERAGELINK : dval += Dist; nvals++; break; + } + } + } + } + } + } + if (linkage_ == AVERAGELINK) + dval /= (double)nvals; + + return dval; +} diff --git a/src/Cluster/Algorithm_HierAgglo.h b/src/Cluster/Algorithm_HierAgglo.h new file mode 100644 index 0000000000..1d8ee42fb6 --- /dev/null +++ b/src/Cluster/Algorithm_HierAgglo.h @@ -0,0 +1,54 @@ +#ifndef INC_CLUSTER_ALGORITHM_HIERAGGLO_H +#define INC_CLUSTER_ALGORITHM_HIERAGGLO_H +#include "Algorithm.h" +#include "DynamicMatrix.h" +#include "List.h" +#include "../CpptrajFile.h" +#include "../Timer.h" +namespace Cpptraj { +namespace Cluster { +class Metric; +/// Implement hierarchical agglomerative clustering +class Algorithm_HierAgglo : public Algorithm { + public: + Algorithm_HierAgglo(); + static void Help(); + int Setup(ArgList&); + void Info() const; + void Results(CpptrajFile&) const; + int DoClustering(List&, Cframes const&, MetricArray&); + void Timing(double) const; + double ClusterDistance(Node const&, Node const&, MetricArray&, + bool, Cframes const&) const; + private: + void buildInitialClusters(List&, Cframes const&, MetricArray&); + //void InitializeClusterDistances(); + int MergeClosest(List&, MetricArray&); + static inline double minDist(Node const&, Node const&, MetricArray&); + static inline double maxDist(Node const&, Node const&, MetricArray&); + static inline double avgDist(Node const&, Node const&, MetricArray&); + // TODO: Node instead of cluster_it? + void calcMinDist(List::cluster_it&, List&, MetricArray&); + void calcMaxDist(List::cluster_it&, List&, MetricArray&); + void calcAvgDist(List::cluster_it&, List&, MetricArray&); + + /// Type of distance calculation between clusters; corresponds to LinkageString_. + enum LINKAGETYPE { SINGLELINK = 0, AVERAGELINK, COMPLETELINK }; + /// Describe LINKAGETYPE + static const char* LinkageString_[]; + + int nclusters_; ///< Target # of clusters. + double epsilon_; ///< Once the min distance between clusters is > epsilon, stop. + LINKAGETYPE linkage_; ///< Cluster Linkage type. + CpptrajFile eps_v_n_; ///< Write epsilon vs # clusters. + DynamicMatrix ClusterDistances_; +# ifdef TIMER + Timer time_findMin_; + Timer time_mergeFrames_; + Timer time_calcLinkage_; +# endif +}; + +} /* END namespace Cluster */ +} /* END namespace Cpptraj */ +#endif diff --git a/src/Cluster/Algorithm_Kmeans.cpp b/src/Cluster/Algorithm_Kmeans.cpp new file mode 100644 index 0000000000..a1d4e317bf --- /dev/null +++ b/src/Cluster/Algorithm_Kmeans.cpp @@ -0,0 +1,429 @@ +#include "Algorithm_Kmeans.h" +#include "Cframes.h" +#include "List.h" +#include "MetricArray.h" +#include "Node.h" +#include "../ArgList.h" +#include "../CpptrajFile.h" +#include "../CpptrajStdio.h" +#include "../ProgressBar.h" + +/** CONSTRUCTOR */ +Cpptraj::Cluster::Algorithm_Kmeans::Algorithm_Kmeans() : + Algorithm(KMEANS), + nclusters_(0), + kseed_(-1), + maxIt_(100), + mode_(SEQUENTIAL), + clusterToClusterCentroid_(false) +{} + +/** Print help to stdout. */ +void Cpptraj::Cluster::Algorithm_Kmeans::Help() { + mprintf("\t[kmeans clusters [randompoint [kseed ]] [maxit ]]\n"); +} + +// SetupCluster() +/** Set up kmeans clustering. */ +int Cpptraj::Cluster::Algorithm_Kmeans::Setup(ArgList& analyzeArgs) { + nclusters_ = analyzeArgs.getKeyInt("clusters", -1); + if (nclusters_ < 2) { + mprinterr("Error: Specify number of clusters > 1 for K-means algorithm.\n"); + return 1; + } + if (analyzeArgs.hasKey("randompoint")) + mode_ = RANDOM; + else + mode_ = SEQUENTIAL; + kseed_ = analyzeArgs.getKeyInt("kseed", -1); + maxIt_ = analyzeArgs.getKeyInt("maxit", 100); + return 0; +} + +// ClusteringInfo() +/** Print kmeans clustering info. */ +void Cpptraj::Cluster::Algorithm_Kmeans::Info() const { + mprintf("\tK-MEANS: Looking for %i clusters.\n", nclusters_); + if (mode_ == SEQUENTIAL) + mprintf("\t\tSequentially modify each point.\n"); + else + mprintf("\t\tRandomly pick points for modification.\n"); + if (kseed_ != -1 && mode_ == RANDOM) + mprintf("\t\tSeed for random number generator: %i\n", kseed_); + mprintf("\tCluster to cluster distance will be based on"); + if (clusterToClusterCentroid_) + mprintf(" best representative from cluster.\n"); + else + mprintf(" cluster centroids.\n"); +} + +// ClusterResults() +/** Write kemans info to info file. */ +void Cpptraj::Cluster::Algorithm_Kmeans::Results(CpptrajFile& outfile) const { + outfile.Printf("#Algorithm: Kmeans nclusters %i maxit %i\n", nclusters_, maxIt_); +} + +// Cpptraj::Cluster::Algorithm_Kmeans::Cluster() +/** Perform kmeans clustering. */ +int Cpptraj::Cluster::Algorithm_Kmeans::DoClustering(List& clusters, + Cframes const& framesToCluster, + MetricArray& pmatrix) +{ + if (mode_ == RANDOM) + RN_.rn_set( kseed_ ); + + int pointCount = (int)framesToCluster.size(); + + // This array will hold the indices of the points to process each iteration. + // If sequential this is just 0 -> pointCount. If random this will be + // reassigned each iteration. + Iarray PointIndices; + PointIndices.reserve( pointCount ); + for (int processIdx = 0; processIdx != pointCount; processIdx++) + PointIndices.push_back( processIdx ); + + int startIteration = 0; + if (clusters.empty()) { + // Determine seeds TODO have FindKmeansSeeds return Iarray with frame #s? + FindKmeansSeeds( framesToCluster, pmatrix ); + // Add the seed clusters + for (Iarray::const_iterator seedIdx = SeedIndices_.begin(); + seedIdx != SeedIndices_.end(); ++seedIdx) + { + int seedFrame = framesToCluster[ *seedIdx ]; + // A centroid is created for new clusters. + clusters.AddCluster( Node(pmatrix, Cframes(1, seedFrame), clusters.Nclusters()) ); + // NOTE: No need to calc best rep frame, only 1 frame. + if (debug_ > 0) + mprintf("Put frame %i in cluster %i (seed index=%i).\n", + seedFrame, clusters.back().Num(), *seedIdx); + } + } else { + // Clusters already exist. + mprintf("\t%i existing clusters.\n", clusters.Nclusters()); + if (clusters.Nclusters() > nclusters_) { + // We currently have more clusters than target clusters. + // Keep the top nclusters_ clusters and break up the rest. + mprintf("\tNumber of input clusters %i larger than target number of clusters %i.\n" + "\tRemoving low-population clusters.\n", clusters.Nclusters(), + nclusters_); + clusters.Sort(); + while (clusters.Nclusters() > nclusters_) { + List::cluster_it lastCluster = clusters.end(); + --lastCluster; + clusters.RemoveCluster( lastCluster ); + } + mprintf("\tNow %i existing clusters.\n", clusters.Nclusters()); + } else if (clusters.Nclusters() < nclusters_) { + // We have fewer clusters than target clusters. + // Try to find new seeds to make up the difference. + mprintf("\tNumber of input clusters %i smaller than target number of clusters %i.\n", + clusters.Nclusters(), nclusters_); + mprintf("\tWill attempt to find seeds from existing clusters.\n"); + Iarray Seeds = FindSeedsFromClusters(clusters, pmatrix); + if (Seeds.empty()) { + mprinterr("Error: Finding seeds from existing clusters failed.\n"); + return 1; + } + // Add the seed clusters + for (Iarray::const_iterator seed = Seeds.begin(); seed != Seeds.end(); ++seed) + { + // A centroid is created for new clusters. + clusters.AddCluster( Node(pmatrix, Cframes(1, *seed), clusters.Nclusters()) ); + // NOTE: No need to calc best rep frame, only 1 frame. + if (debug_ > 0) + mprintf("Put frame %i in cluster %i.\n", *seed, clusters.back().Num()); + } + } + + // Ensure centroids are up to date. + clusters.UpdateCentroids( pmatrix ); + // Since clusters already exist, go beyond the initial pass. + startIteration = 1; + } + + // Assign points in 3 passes. If a point looked like it belonged to cluster A + // at first, but then we added many other points and altered our cluster + // shapes, its possible that we will want to reassign it to cluster B. + for (int iteration = startIteration; iteration != maxIt_; iteration++) + { + if (mode_ == RANDOM) { + RN_.ShufflePoints( PointIndices ); + if (debug_ > 0) { + mprintf("DEBUG: Shuffled points:"); + for (Iarray::const_iterator it = PointIndices.begin(); + it != PointIndices.end(); ++it) + mprintf(" %i", *it); + mprintf("\n"); + } + } + + // Add each point to an existing cluster, and recompute centroid + mprintf("\tRound %i: ", iteration); + ProgressBar progress( PointIndices.size() ); + int Nchanged = 0; + int prog = 0; + for (Iarray::const_iterator pointIdx = PointIndices.begin(); + pointIdx != PointIndices.end(); ++pointIdx, ++prog) + { + if (debug_ < 1) progress.Update( prog ); + int oldClusterIdx = -1; +// if ( iteration != 0 || mode_ != SEQUENTIAL) +// { + int pointFrame = framesToCluster[ *pointIdx ]; + if (debug_ > 0) + mprintf("DEBUG: Processing frame %i (index %i)\n", pointFrame, *pointIdx); + bool pointWasYanked = true; + if (iteration > 0) { + // Yank this point out of its cluster, recompute the centroid + for (List::cluster_it C1 = clusters.begin(); C1 != clusters.end(); ++C1) + { + if (C1->HasFrame( pointFrame )) + { + // If this point is alone in its cluster its in the right place + if (C1->Nframes() == 1) { + pointWasYanked = false; + break; + } + //oldBestRep = C1->BestRepFrame(); + oldClusterIdx = C1->Num(); + C1->RemoveFrameUpdateCentroid( pmatrix, pointFrame ); // TEST +// C1->RemoveFrameFromCluster( pointFrame ); + //newBestRep = C1->FindBestRepFrame(); +// C1->CalculateCentroid( pmatrix.MetricPtr() ); + if (debug_ > 0) + mprintf("Remove Frame %i from cluster %i\n", pointFrame, C1->Num()); + //if (clusterToClusterCentroid_) { + // if (oldBestRep != NewBestRep) + // C1->AlignToBestRep( pmatrix.MetricPtr() ); // Only relevant for COORDS dist? + // C1->CalculateCentroid( pmatrix.MetricPtr() ); // TODO Seems unnessecary to align prior + //} + } + } + } else { + // First iteration. If this point is already in a cluster it is a seed. + for (List::cluster_it C1 = clusters.begin(); C1 != clusters.end(); ++C1) + { + if (C1->HasFrame( pointFrame )) { + pointWasYanked = false; + if (debug_ > 0) + mprintf("Frame %i was already used to seed cluster %i\n", + pointFrame, C1->Num()); + break; + } + } + } + if (pointWasYanked) { + // Find out what cluster this point is now closest to. + double closestDist = -1.0; + List::cluster_it closestCluster = clusters.begin(); + for (List::cluster_it C1 = clusters.begin(); C1 != clusters.end(); ++C1) + { + double dist = pmatrix.FrameCentroidDist(pointFrame, C1->Cent()); + if (closestDist < 0.0 || dist < closestDist) + { + closestDist = dist; + closestCluster = C1; + } + } + //oldBestRep = closestCluster->BestRepFrame(); + closestCluster->AddFrameUpdateCentroid( pmatrix, pointFrame ); // TEST +// closestCluster->AddFrameToCluster( pointFrame ); + //newBestRep = closestCluster->FindBestFrameFrame(); +// closestCluster->CalculateCentroid( pmatrix.MetricPtr() ); + if (closestCluster->Num() != oldClusterIdx) + { + Nchanged++; + if (debug_ > 0) + mprintf("Remove Frame %i from cluster %i, but add to cluster %i (dist= %f).\n", + pointFrame, oldClusterIdx, closestCluster->Num(), closestDist); + } else { + if (debug_ > 0) + mprintf("Frame %i staying in cluster %i (dist= %f)\n", + pointFrame, closestCluster->Num(), closestDist); + } + //if (clusterToClusterCentroid_) { + //if (oldBestRep != NewBestRep) { + // C1->AlignToBestRep( pmatrix.MetricPtr() ); // Only relevant for COORDS dist? + // C1->CalculateCentroid( pmatrix.MetricPtr() ); // TODO Seems unnessecary to align prior + //} + //} + } +// } + } // END loop over points to cluster + if (Nchanged == 0) { + mprintf("\tK-means round %i: No change. Skipping the rest of the iterations.\n", iteration); + break; + } else + mprintf("\tK-means round %i: %i points changed cluster assignment.\n", iteration, Nchanged); + } // END k-means iterations + // Remove any empty clusters + clusters.RemoveEmptyClusters(); + // NOTE in PTRAJ here align all frames to best rep + return 0; +} + +// FindSeedsFromClusters +/** Given current clusters, find points that are far away from centroids + * that can be used as new cluster seeds. + * \return Array containing frame numbers to be used as seeds. + */ +Cpptraj::Cluster::Algorithm_Kmeans::Iarray + Cpptraj::Cluster::Algorithm_Kmeans::FindSeedsFromClusters(List& clusters, + MetricArray& pmatrix) +const +{ + // TODO change algorithm to do normal seed choice, then pick seeds that are + // far away from existing centroids. + int nSeedsToFind = nclusters_ - clusters.Nclusters(); + mprintf("\tTarget # seeds= %i\n", nSeedsToFind); + if (nSeedsToFind < 1) return Iarray(); + // Ensure centroids are up to date + clusters.UpdateCentroids( pmatrix ); + Iarray Seeds( nSeedsToFind, -1 ); + int nSeedsFound = 0; + while (nSeedsFound < nSeedsToFind) + { + // Find the farthest point in each cluster. + std::vector MaxDst; + std::vector MaxFrame; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node) + { + double maxdist = 0; + int maxframe = -1; + + for (Node::frame_iterator frm = node->beginframe(); frm != node->endframe(); ++frm) + { + double dist = pmatrix.FrameCentroidDist(*frm, node->Cent()); + if (dist > maxdist) { + maxdist = dist; + maxframe = *frm; + } + } + if (debug_ > 0) + mprintf("DEBUG: cluster %i seed %i maxdist= %f maxframe= %i\n", + node->Num(), nSeedsFound, maxdist, maxframe); + MaxDst.push_back( maxdist ); + MaxFrame.push_back( maxframe ); + } + if (nSeedsFound == 0) { + // For the first seed, just choose the one with the largest distance to centroid. + int maxi = -1; + double maxd = 0; + List::cluster_it maxclust = clusters.end(); + int idx = 0; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node, idx++) + { + if (MaxDst[idx] > maxd) { + maxd = MaxDst[idx]; + maxi = idx; + maxclust = node; + } + } + maxclust->RemoveFrameUpdateCentroid( pmatrix, MaxFrame[maxi] ); + Seeds[nSeedsFound++] = MaxFrame[maxi]; + if (debug_ > 0) + mprintf("DEBUG: Frame %i from cluster %i (%f) chosen as first seed.\n", + MaxFrame[maxi], maxi, MaxDst[maxi]); + } else { + // Out of the list of farthest points, choose the one with the largest + // cumulative distance to existing seeds. + std::vector cumulativeDist; + int maxi = -1; + double maxd = 0; + List::cluster_it maxclust = clusters.end(); + int idx = 0; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node, idx++) + { + double cdist = 0; + int frm1 = MaxFrame[idx]; + for (int is = 0; is < nSeedsFound; is++) + cdist += pmatrix.Frame_Distance(frm1, Seeds[is]); + if (cdist > maxd) { + maxd = cdist; + maxi = idx; + maxclust = node; + } + } + if (debug_ > 0) + mprintf("DEBUG: Frame %i from cluster %i (%f, %f) chosen as seed %i.\n", + MaxFrame[maxi], maxi, MaxDst[maxi], maxd, nSeedsFound); + maxclust->RemoveFrameUpdateCentroid( pmatrix, MaxFrame[maxi] ); + Seeds[nSeedsFound++] = MaxFrame[maxi]; + } + + } + + return Seeds; +} + +// FindKmeansSeeds() +/** Find some seed-points for K-means clustering. Take the first point as an + * arbitrary first choice. Then, at each iteration, add the point whose total + * distance from our set of seeds is as large as possible. + */ +int Cpptraj::Cluster::Algorithm_Kmeans::FindKmeansSeeds(Cframes const& FramesToCluster, + MetricArray& pmatrix) +{ + // SeedIndices will hold indices into FramesToCluster + SeedIndices_.resize( nclusters_, 1 ); // 1 used to be consistent with ptraj + + double bestDistance = 0.0; + int frameCount = (int)FramesToCluster.size(); + for (int frameIdx = 0; frameIdx != frameCount; frameIdx++) + { + int seedFrame = FramesToCluster[ frameIdx ]; + for (int candidateIdx = frameIdx; candidateIdx < frameCount; candidateIdx++) + { + int candidateFrame = FramesToCluster[ candidateIdx ]; + double dist = pmatrix.Frame_Distance( seedFrame, candidateFrame ); + if (dist > bestDistance) + { + bestDistance = dist; + SeedIndices_[0] = frameIdx; + SeedIndices_[1] = candidateIdx; + } + } + } + + for (int seedIdx = 2; seedIdx != nclusters_; seedIdx++) + { + bestDistance = 0.0; + int bestIdx = 0; + for (int candidateIdx = 0; candidateIdx < frameCount; candidateIdx++) + { + // Make sure this candidate isnt already a seed + bool skipCandidate = false; + for (int checkIdx = 0; checkIdx != seedIdx; checkIdx++) + { + if (SeedIndices_[checkIdx] == candidateIdx) { + skipCandidate = true; + break; + } + } + if (!skipCandidate) { + // Get the closest distance from this candidate to a current seed + int candidateFrame = FramesToCluster[ candidateIdx ]; + double nearestDist = -1.0; + for (int checkIdx = 0; checkIdx != seedIdx; checkIdx++) + { + int seedFrame = FramesToCluster[ SeedIndices_[checkIdx] ]; + double dist = pmatrix.Frame_Distance( candidateFrame, seedFrame ); + if (dist < nearestDist || nearestDist < 0.0) + nearestDist = dist; + } + // Is this the best so far? + if (nearestDist > bestDistance) + { + bestDistance = nearestDist; + bestIdx = candidateIdx; + } + } + } + SeedIndices_[seedIdx] = bestIdx; + } + if (debug_ > 0) + for (unsigned int si = 0; si != SeedIndices_.size(); si++) + mprintf("DEBUG:\t\tSeedIndices[%u]= %i\n", si, SeedIndices_[si]); + return 0; +} diff --git a/src/Cluster/Algorithm_Kmeans.h b/src/Cluster/Algorithm_Kmeans.h new file mode 100644 index 0000000000..0b23a6eae4 --- /dev/null +++ b/src/Cluster/Algorithm_Kmeans.h @@ -0,0 +1,36 @@ +#ifndef INC_CLUSTER_ALGORITHM_KMEANS_H +#define INC_CLUSTER_ALGORITHM_KMEANS_H +#include "Algorithm.h" +#include "../Random.h" +namespace Cpptraj { +namespace Cluster { + +/// Implement K-means clustering +class Algorithm_Kmeans : public Algorithm { + public: + Algorithm_Kmeans(); + static void Help(); + int Setup(ArgList&); + void Info() const; + void Results(CpptrajFile&) const; + int DoClustering(List&, Cframes const&, MetricArray&); + void Timing(double) const {} + private: + typedef std::vector Iarray; + enum KmeansModeType { SEQUENTIAL, RANDOM }; + + Iarray FindSeedsFromClusters(List&, MetricArray&) const; + int FindKmeansSeeds(Cframes const&, MetricArray&); + + Random_Number RN_; + int nclusters_; ///< Target number of clusters. + int kseed_; + int maxIt_; + Iarray SeedIndices_; ///< Hold indices into framesToCluster of seed frames + KmeansModeType mode_; + bool clusterToClusterCentroid_; +}; + +} +} +#endif diff --git a/src/Cluster/BestReps.cpp b/src/Cluster/BestReps.cpp new file mode 100644 index 0000000000..3db4172a33 --- /dev/null +++ b/src/Cluster/BestReps.cpp @@ -0,0 +1,315 @@ +#include "BestReps.h" +#include "List.h" +#include "MetricArray.h" +#include "Node.h" +#include "../CpptrajStdio.h" + +/** CONSTRUCTOR */ +Cpptraj::Cluster::BestReps::BestReps() : + debug_(0), + nToSave_(0), + type_(NO_REPS) +{} + +/** Save up to maxSize of the best (lowest) representative scores/frames. */ +void Cpptraj::Cluster::BestReps::SaveBestRep(RepMap& reps, RepPair const& Dist_Num, + unsigned int maxSize) +{ + if (reps.size() < maxSize) + reps.insert( Dist_Num ); + else { + RepMap::reverse_iterator end = reps.rbegin(); + if (Dist_Num.first < end->first) { + reps.insert( Dist_Num ); + if (reps.size() > maxSize) { + RepMap::iterator it = reps.end(); + --it; + reps.erase( it ); + } + } + } +} + +/** Set given cluster node with best representative frames/scores in reps */ +void Cpptraj::Cluster::BestReps::SetBestRepFrame(Node& node, RepMap const& reps) +{ + if (!reps.empty()) { + node.BestReps().clear(); + for (RepMap::const_iterator it = reps.begin(); it != reps.end(); ++it) { + node.BestReps().push_back( Node::RepPair(it->second, it->first) ); + } + } +} + +/** Initialize best rep find. */ +int Cpptraj::Cluster::BestReps::InitBestReps(RepMethodType typeIn, int nToSaveIn, int debugIn) +{ + // TODO some error checking + type_ = typeIn; + nToSave_ = nToSaveIn; + debug_ = debugIn; + return 0; +} + +/** Print best reps to stdout. */ +void Cpptraj::Cluster::BestReps::PrintBestReps(Node const& node) { + mprintf("DEBUG: Cluster %i best reps:\n", node.Num()); + for (Node::RepPairArray::const_iterator it = node.BestReps().begin(); + it != node.BestReps().end(); ++it) + mprintf("\t%i (%g)\n", it->first, it->second); +} + +/** Find best representative frames for each cluster. */ +int Cpptraj::Cluster::BestReps::FindBestRepFrames(List& clusters, MetricArray& pmatrix, + Cframes const& sievedFrames) +const +{ + int err = 0; + switch (type_) { + case CUMULATIVE: + err = FindBestRepFrames_CumulativeDist(clusters, pmatrix); + break; + case CENTROID: + err = FindBestRepFrames_Centroid(clusters, pmatrix); + break; + case CUMULATIVE_NOSIEVE: + err = FindBestRepFrames_NoSieve_CumulativeDist(clusters, pmatrix, sievedFrames); + break; + case NO_REPS: + mprintf("Warning: Skipping best representative frame calc.\n"); + break; + default: + mprinterr("Internal Error: BestReps::FindBestRepFrames: Unhandled type.\n"); + err = 1; + } + + // DEBUG + if (debug_ > 0) { + for (List::cluster_iterator node = clusters.begin(); node != clusters.end(); ++node) + PrintBestReps(*node); + } + + return err; +} + +/** Find best representative frames for given node. */ +int Cpptraj::Cluster::BestReps::FindBestRepFrames(Node& node, MetricArray& pmatrix, + Cframes const& sievedFrames) +const +{ + int err = 0; + switch (type_) { + case CUMULATIVE: + err = FindBestRepFrames_CumulativeDist(node, pmatrix); + break; + case CENTROID: + err = FindBestRepFrames_Centroid(node, pmatrix); + break; + case CUMULATIVE_NOSIEVE: + err = FindBestRepFrames_NoSieve_CumulativeDist(node, pmatrix, sievedFrames); + break; + case NO_REPS: + mprintf("Warning: Skipping best representative frame calc.\n"); + break; + default: + mprinterr("Internal Error: BestReps::FindBestRepFrames: Unhandled type.\n"); + err = 1; + } + + // DEBUG + if (debug_ > 0) + PrintBestReps(node); + + return err; +} + +/** Find the frame(s) in the node that is best representative by + * having the lowest cumulative distance to every other point in the cluster. + */ +int Cpptraj::Cluster::BestReps::FindBestRepFrames_CumulativeDist(Node& node, + MetricArray& pmatrix) +const +{ + int err = 0; + //node.Cent()->Print("centroid." + integerToString(node.Num())); // DEBUG + //CpptrajFile tmp; // DEBUG + //tmp.OpenWrite("c"+integerToString(node.Num())+".bestRep.dat"); // DEBUG + // Handle special cases + if (node.Nframes() == 1) { + node.BestReps().clear(); + if (debug_ > 0) + mprintf("DEBUG: Only 1 frame, best rep: %i\n", node.ClusterFrame(0)); + // Only one frame. That is the best rep. + node.BestReps().push_back( RepPair(node.ClusterFrame(0), 0.0) ); + } else if (node.Nframes() == 2) { + node.BestReps().clear(); + if (debug_ > 0) + mprintf("DEBUG: 2 frames %i and %i, using former as best rep.\n", + node.ClusterFrame(0), node.ClusterFrame(1)); + // Two frames, distance from f1 to f2 same as f2 to f1. Take f1 by convention. + node.BestReps().push_back(RepPair(node.ClusterFrame(0), + pmatrix.Frame_Distance(node.ClusterFrame(0), node.ClusterFrame(1)))); + } else { + // Find cumulative distance of each frame to all other frames. + RepMap bestReps; + for (Node::frame_iterator f1 = node.beginframe(); f1 != node.endframe(); ++f1) + { + double cdist = 0.0; + for (Node::frame_iterator f2 = node.beginframe(); f2 != node.endframe(); ++f2) + { + if (f1 != f2) + cdist += pmatrix.Frame_Distance(*f1, *f2); + } + SaveBestRep(bestReps, RepPair(cdist, *f1), nToSave_); + //tmp.Printf("%i %g %g\n", *f1+1, cdist, Cdist_->FrameCentroidDist(*f1, node.Cent())); + } + //tmp.CloseFile(); + if (bestReps.empty()) { + mprinterr("Error: Could not determine represenative frame for cluster %i\n", + node.Num()); + err++; + } + SetBestRepFrame( node, bestReps ); + // DEBUG + if (debug_ > 0) { + mprintf("DEBUG: Best reps:\n"); + for (RepMap::const_iterator it = bestReps.begin(); it != bestReps.end(); ++it) + mprintf("\t%i (%20.10E)\n", it->second, it->first); + } + } + return err; +} + +// ClusterList::FindBestRepFrames_CumulativeDist() +/** Find the frame in each cluster that is the best representative by + * having the lowest cumulative distance to every other point in the cluster. + */ +int Cpptraj::Cluster::BestReps::FindBestRepFrames_CumulativeDist(List& clusters, + MetricArray& pmatrix) +const +{ + int err = 0; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node) { + err += FindBestRepFrames_CumulativeDist(*node, pmatrix); + } + return err; +/* + int err = 0; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node) { + //node->Cent()->Print("centroid." + integerToString(node->Num())); // DEBUG + //CpptrajFile tmp; // DEBUG + //tmp.OpenWrite("c"+integerToString(node->Num())+".bestRep.dat"); // DEBUG + RepMap bestReps; + for (Node::frame_iterator f1 = node->beginframe(); f1 != node->endframe(); ++f1) + { + double cdist = 0.0; + for (Node::frame_iterator f2 = node->beginframe(); f2 != node->endframe(); ++f2) + { + if (f1 != f2) + cdist += pmatrix.Frame_Distance(*f1, *f2); + } + SaveBestRep(bestReps, RepPair(cdist, *f1), nToSave); + //tmp.Printf("%i %g %g\n", *f1+1, cdist, Cdist_->FrameCentroidDist(*f1, node->Cent())); + } + //tmp.CloseFile(); + if (bestReps.empty()) { + mprinterr("Error: Could not determine represenative frame for cluster %i\n", + node->Num()); + err++; + } + SetBestRepFrame( *node, bestReps ); + } + return err; +*/ +} + +/** Find the frame in Node that is the best representative by + * having the lowest cumulative distance to every other point in the cluster, + * ignoring sieved frames. + */ +int Cpptraj::Cluster::BestReps:: + FindBestRepFrames_NoSieve_CumulativeDist(Node& node, MetricArray& pmatrix, + Cframes const& sievedFrames) +const +{ + int err = 0; + RepMap bestReps; + for (Node::frame_iterator f1 = node.beginframe(); f1 != node.endframe(); ++f1) + { + if (!sievedFrames.HasFrame( *f1 )) { + double cdist = 0.0; + for (Node::frame_iterator f2 = node.beginframe(); f2 != node.endframe(); ++f2) + { + if (f1 != f2 && !sievedFrames.HasFrame( *f2 )) + //cdist += pmatrix.Cache().CachedDistance(*f1, *f2); // TODO benchmark the two ways + cdist += pmatrix.Frame_Distance(*f1, *f2); + } + SaveBestRep(bestReps, RepPair(cdist, *f1), nToSave_); + } + } + if (bestReps.empty()) { + mprinterr("Error: Could not determine represenative frame for cluster %i\n", + node.Num()); + err++; + } + SetBestRepFrame( node, bestReps ); + return err; +} + +/** Find the frame in each cluster that is the best representative by + * having the lowest cumulative distance to every other point in the cluster, + * ignoring sieved frames. + */ +int Cpptraj::Cluster::BestReps:: + FindBestRepFrames_NoSieve_CumulativeDist(List& clusters, MetricArray& pmatrix, + Cframes const& sievedFrames) +const +{ + if (sievedFrames.size() > 0) + mprintf("Warning: Ignoring sieved frames while looking for best representative.\n"); + int err = 0; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node) { + err += FindBestRepFrames_NoSieve_CumulativeDist(*node, pmatrix, sievedFrames); + } + return err; +} + +/** Find the frame in the node that is the best representative by + * having the lowest distance to the cluster centroid. + */ +int Cpptraj::Cluster::BestReps::FindBestRepFrames_Centroid(Node& node, + MetricArray& pmatrix) +const +{ + int err = 0; + //mprintf("DEBUG: FindBestRepFrames_Centroid: Cluster %i\n", node.Num()); + RepMap bestReps; + //node.Cent()->Print("centroid." + integerToString(node.Num())); // DEBUG + for (Node::frame_iterator f1 = node.beginframe(); f1 != node.endframe(); ++f1) + { + double dist = pmatrix.FrameCentroidDist(*f1, node.Cent()); + //mprintf("\t%8i %10.4g %10.4g %i\n", *f1+1, dist, mindist, minframe+1); + SaveBestRep(bestReps, RepPair(dist, *f1), nToSave_); + } + if (bestReps.empty()) { + mprinterr("Error: Could not determine represenative frame for cluster %i\n", + node.Num()); + err++; + } + SetBestRepFrame( node, bestReps ); + return err; +} + +/** Find the frame in each cluster that is the best representative by + * having the lowest distance to the cluster centroid. + */ +int Cpptraj::Cluster::BestReps::FindBestRepFrames_Centroid(List& clusters, + MetricArray& pmatrix) +const +{ + int err = 0; + for (List::cluster_it node = clusters.begin(); node != clusters.end(); ++node) { + err += FindBestRepFrames_Centroid(*node, pmatrix); + } + return err; +} diff --git a/src/Cluster/BestReps.h b/src/Cluster/BestReps.h new file mode 100644 index 0000000000..6d4dfb33bc --- /dev/null +++ b/src/Cluster/BestReps.h @@ -0,0 +1,58 @@ +#ifndef INC_CLUSTER_BESTREPS_H +#define INC_CLUSTER_BESTREPS_H +#include +namespace Cpptraj { +namespace Cluster { +class Cframes; +class List; +class MetricArray; +class Node; +/// Used to find best representative structures for a cluster. +class BestReps { + public: + enum RepMethodType { NO_REPS = 0, CUMULATIVE, CENTROID, CUMULATIVE_NOSIEVE }; + + /// CONSTRUCTOR + BestReps(); + + /// Initialize best rep frames search with method type, # to save, and debug level + int InitBestReps(RepMethodType, int, int); + /// Find best rep frames for each cluster in given list + int FindBestRepFrames(List&, MetricArray&, Cframes const&) const; + /// Find the best rep frames for given node + int FindBestRepFrames(Node&, MetricArray&, Cframes const&) const; + private: + /// Print best reps to stdout + static void PrintBestReps(Node const&); + + /// Used to pair representative score with frame number. + typedef std::pair RepPair; + /// Used to hold pairs of representative scores to frames. + typedef std::multimap RepMap; + + /// Save up to maxSize of the best (lowest) representative scores/frames. + static inline void SaveBestRep(RepMap&, RepPair const&, unsigned int); + /// Set given cluster node with best representative frames/scores in reps + static inline void SetBestRepFrame(Node& node, RepMap const&); + + /// Find best rep frames in node by shortest distance to all other frames. + int FindBestRepFrames_CumulativeDist(Node&, MetricArray&) const; + /// Find best representative frames by shortest distance to all other frames. + int FindBestRepFrames_CumulativeDist(List&, MetricArray&) const; + /// Find best rep frames in node by shortest distance, ignoring sieved frames. + int FindBestRepFrames_NoSieve_CumulativeDist(Node&, MetricArray&, Cframes const&) const; + /// Find best representative frames by shortest distance, ignoring sieved frames. + int FindBestRepFrames_NoSieve_CumulativeDist(List&, MetricArray&, Cframes const&) const; + /// Find best rep frames in node by shortest distance to centroid. + int FindBestRepFrames_Centroid(Node&, MetricArray&) const; + /// Find best representative frames by shortest distance to centroid. + int FindBestRepFrames_Centroid(List&, MetricArray&) const; + + int debug_; ///< Debug level, set in call to FindBestRepFrames + int nToSave_; ///< Number of representatives to find + RepMethodType type_; ///< Method to use to find best reps +}; + +} +} +#endif diff --git a/src/Cluster/CMakeLists.txt b/src/Cluster/CMakeLists.txt new file mode 100644 index 0000000000..c9ad5d9ceb --- /dev/null +++ b/src/Cluster/CMakeLists.txt @@ -0,0 +1,44 @@ +#CMake buildfile for CPPTRAJ Cluster subdirectory. +set(CLUSTER_SOURCES + Algorithm.cpp + Algorithm_DBscan.cpp + Algorithm_DPeaks.cpp + Algorithm_HierAgglo.cpp + Algorithm_Kmeans.cpp + BestReps.cpp + Centroid_Coord.cpp + CentroidArray.cpp + Cframes.cpp + Cmatrix_Binary.cpp + Cmatrix_NC.cpp + Control.cpp + DrawGraph.cpp + DynamicMatrix.cpp + List.cpp + MetricArray.cpp + Metric_DME.cpp + Metric_RMS.cpp + Metric_Scalar.cpp + Metric_SRMSD.cpp + Metric_Torsion.cpp + Node.cpp + Output.cpp + Results_Coords.cpp + Sieve.cpp +) + +#------------------------------------------------------------------------------------------ +#I assume that this library should be optimized +#add_compile_options(${OPT_CXXFLAGS_SPC}) +set_property(SOURCE ${CLUSTER_SOURCES} PROPERTY COMPILE_FLAGS "${OPT_CXXFLAGS_SPC}") + +#if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") +# # xdrfile is not set up to build as a Windows shared library. Someone would need to add dll exports to all of the symbols (bluh) +# add_library(xdrfile STATIC ${CLUSTER_SOURCES}) +#else() + add_library(cpptraj_cluster STATIC ${CLUSTER_SOURCES}) + make_pic_if_needed(cpptraj_cluster) +#endif() + +target_include_directories(cpptraj_cluster PUBLIC . PRIVATE $) +install_libraries(cpptraj_cluster) diff --git a/src/Cluster/Centroid.h b/src/Cluster/Centroid.h new file mode 100644 index 0000000000..a5b46207b2 --- /dev/null +++ b/src/Cluster/Centroid.h @@ -0,0 +1,25 @@ +#ifndef INC_CLUSTER_CENTROID_H +#define INC_CLUSTER_CENTROID_H +#include +namespace Cpptraj { +namespace Cluster { + +/// Abstract Base Class for Cluster centroid. +/** This class is a container for the cluster centroid type appropriate for + * the data being clustered. For COORDS DataSets this is a frame, for other + * DataSets this is just a number. Centroid classes must implement a Copy() + * function. + */ +class Centroid { + public: + virtual ~Centroid() {} + virtual Centroid* Copy() = 0; + // TODO: Should centroids remember number of frames that went into them? + // This would make it so FrameOpCentroid wouldnt require extra arg. + virtual void Print(std::string const&) const {} +}; + + +} // END namespace Cluster +} // END namepsace Cpptraj +#endif diff --git a/src/Cluster/CentroidArray.cpp b/src/Cluster/CentroidArray.cpp new file mode 100644 index 0000000000..43c08d2c69 --- /dev/null +++ b/src/Cluster/CentroidArray.cpp @@ -0,0 +1,35 @@ +#include "CentroidArray.h" +#include "Centroid.h" + +/** CONSTRUCTOR */ +Cpptraj::Cluster::CentroidArray::CentroidArray() {} + +/** DESTRUCTOR */ +Cpptraj::Cluster::CentroidArray::~CentroidArray() { + Clear(); +} + +/** COPY CONSTRUCTOR */ +Cpptraj::Cluster::CentroidArray::CentroidArray(CentroidArray const& rhs) { + centroids_.reserve( rhs.centroids_.size() ); + for (std::vector::const_iterator it = rhs.centroids_.begin(); it != rhs.centroids_.end(); ++it) + centroids_.push_back( (*it)->Copy() ); +} + +/** ASSIGNMENT */ +Cpptraj::Cluster::CentroidArray& + Cpptraj::Cluster::CentroidArray::operator=(CentroidArray const& rhs) +{ + if (this == &rhs) return *this; + centroids_.clear(); + centroids_.reserve( rhs.centroids_.size() ); + for (std::vector::const_iterator it = rhs.centroids_.begin(); it != rhs.centroids_.end(); ++it) + centroids_.push_back( (*it)->Copy() ); + return *this; +} + +/** Clear the centroid array. */ +void Cpptraj::Cluster::CentroidArray::Clear() { + for (std::vector::iterator it = centroids_.begin(); it != centroids_.end(); ++it) + delete *it; +} diff --git a/src/Cluster/CentroidArray.h b/src/Cluster/CentroidArray.h new file mode 100644 index 0000000000..d6232bf4e9 --- /dev/null +++ b/src/Cluster/CentroidArray.h @@ -0,0 +1,36 @@ +#ifndef CPPTRAJ_CLUSTER_CENTROIDARRAY_H +#define CPPTRAJ_CLUSTER_CENTROIDARRAY_H +#include +namespace Cpptraj { +namespace Cluster { +class Centroid; +/// Hold Centroids of various types +class CentroidArray { + public: + /// CONSTRUCTOR + CentroidArray(); + /// DESTRUCTOR + ~CentroidArray(); + /// COPY + CentroidArray(CentroidArray const&); + /// ASSIGN + CentroidArray& operator=(CentroidArray const&); + /// Clear the centroid array + void Clear(); + + /// \return number of centroids + unsigned int size() const { return centroids_.size(); } + /// \return true if no centroids + bool empty() const { return centroids_.empty(); } + + /// Add given centroid pointer to array + void push_back( Centroid* c) { centroids_.push_back( c ); } + /// \return Centroid pointer at given position + Centroid* operator[](int idx) const { return centroids_[idx]; } + private: + std::vector centroids_; +}; + +} +} +#endif diff --git a/src/Cluster/Centroid_Coord.cpp b/src/Cluster/Centroid_Coord.cpp new file mode 100644 index 0000000000..eed141add4 --- /dev/null +++ b/src/Cluster/Centroid_Coord.cpp @@ -0,0 +1,24 @@ +#ifndef INC_CENTROID_COORD_H +#define INC_CENTROID_COORD_H +#include "Centroid_Coord.h" +#include "../CpptrajFile.h" + +void Cpptraj::Cluster::Centroid_Coord::Print(std::string const& fnameIn) const { + // Write Amber coordinate format + CpptrajFile cOut; + FileName fname(fnameIn); + if (cOut.OpenWrite(fname)) return; + cOut.Printf("%-80s\n", fname.base()); + int col = 0; + for (int ic = 0; ic != cframe_.size(); ic++) { + cOut.Printf("%8.3f", cframe_[ic]); + ++col; + if (col == 10) { + cOut.Printf("\n"); + col = 0; + } + } + if (col > 0) cOut.Printf("\n"); +} + +#endif diff --git a/src/Cluster/Centroid_Coord.h b/src/Cluster/Centroid_Coord.h new file mode 100644 index 0000000000..f185b8e8a9 --- /dev/null +++ b/src/Cluster/Centroid_Coord.h @@ -0,0 +1,27 @@ +#ifndef INC_CLUSTER_CENTROID_COORD_H +#define INC_CLUSTER_CENTROID_COORD_H +#include "../Frame.h" +#include "Centroid.h" +namespace Cpptraj { +namespace Cluster { + +/// Cluster Centroid for Coords DataSet. +class Centroid_Coord : public Centroid { + public: + Centroid_Coord() {} + Centroid_Coord(Frame const& frame) : cframe_(frame) {} + Centroid_Coord(int natom) : cframe_(natom) {} + + Centroid* Copy() { return (Centroid*)new Centroid_Coord(cframe_); } + void Print(std::string const&) const; + + Frame const& Cframe() const { return cframe_; } + Frame& Cframe() { return cframe_; } + private: + Frame cframe_; +}; + + +} +} +#endif diff --git a/src/Cluster/Centroid_Num.h b/src/Cluster/Centroid_Num.h new file mode 100644 index 0000000000..5ce9617307 --- /dev/null +++ b/src/Cluster/Centroid_Num.h @@ -0,0 +1,35 @@ +#ifndef INC_CLUSTER_CENTROID_NUM_H +#define INC_CLUSTER_CENTROID_NUM_H +#include "Centroid.h" +namespace Cpptraj { +namespace Cluster { + +/// Cluster centroid for generic DataSet +class Centroid_Num : public Centroid { + public: + Centroid_Num() : cval_(0.0), sumx_(0.0), sumy_(0.0) {} + Centroid_Num(double val, double x, double y) : cval_(val), sumx_(x), sumy_(y) {} + + Centroid* Copy() { return (Centroid*)new Centroid_Num(cval_, sumx_, sumy_); } + /// \return Current value of average. + double Cval() const { return cval_; } + + /// \return Sum of cos(theta); for periodic average + double SumX() const { return sumx_; } + /// \return Sum of sin(theta); for periodic average + double SumY() const { return sumy_; } + + /// Set average value. + void SetCval(double c) { cval_ = c; } + + /// For periodic average; set sum of cos(theta) and sum of sin(theta) + void SetPeriodicSums(double x, double y) { sumx_ = x; sumy_ = y; } + private: + double cval_; + double sumx_; // For storing periodic average + double sumy_; // For storing periodic average +}; + +} +} +#endif diff --git a/src/Cluster/Cframes.cpp b/src/Cluster/Cframes.cpp new file mode 100644 index 0000000000..cc272a31b3 --- /dev/null +++ b/src/Cluster/Cframes.cpp @@ -0,0 +1,23 @@ +#include +#include "Cframes.h" + +bool Cpptraj::Cluster::Cframes::HasFrame(int frame) const { + Iarray::const_iterator it = std::find(frames_.begin(), frames_.end(), frame); + return !(it == frames_.end()); +} + +int Cpptraj::Cluster::Cframes::FrameIdx(int frame) const { + Iarray::const_iterator it = std::find(frames_.begin(), frames_.end(), frame); + if (it == frames_.end()) return -1; + return (int)(it - frames_.begin()); +} + +void Cpptraj::Cluster::Cframes::Remove(int frame) { + Iarray::iterator pend = std::remove( frames_.begin(), frames_.end(), frame); + std::size_t newsize = pend - frames_.begin(); + frames_.resize( newsize ); +} + +void Cpptraj::Cluster::Cframes::Sort() { + std::sort(frames_.begin(), frames_.end()); +} diff --git a/src/Cluster/Cframes.h b/src/Cluster/Cframes.h new file mode 100644 index 0000000000..0ac15d6ba6 --- /dev/null +++ b/src/Cluster/Cframes.h @@ -0,0 +1,45 @@ +#ifndef INC_CLUSTER_CFRAMES_H +#define INC_CLUSTER_CFRAMES_H +#include +#include // size_t +namespace Cpptraj { +namespace Cluster { + +/// Used to hold frames to cluster (may not be all frames). +class Cframes { + typedef std::vector Iarray; + public: + Cframes() {} + Cframes(std::size_t n, int i) : frames_(n, i) {} + + std::size_t size() const { return frames_.size(); } + typedef Iarray::const_iterator const_iterator; + const_iterator begin() const { return frames_.begin(); } + const_iterator end() const { return frames_.end(); } +/* typedef Iarray::iterator iterator; + iterator begin() { return frames_.begin(); } + iteratir end() */ + int front() const { return frames_.front(); } + int operator[](unsigned int idx) const { return frames_[idx]; } + int& operator[](unsigned int idx) { return frames_[idx]; } + void push_back(int i) { frames_.push_back( i ); } + void assign(std::size_t n, int i) { frames_.assign(n, i); } + void clear() { frames_.clear(); } + void reserve(std::size_t n) { frames_.reserve(n); } + Iarray const& Data() const { return frames_; } + bool empty() const { return frames_.empty(); } + + bool HasFrame(int) const; + int FrameIdx(int) const; + void Insert(Cframes const& rhs) { frames_.insert(frames_.end(), rhs.begin(), rhs.end()); } + void Remove(int); + void Sort(); + private: + Iarray frames_; ///< Frames to cluster. +}; + +typedef Cframes::const_iterator Cframes_it; + +} +} +#endif diff --git a/src/Cluster/Cmatrix_Binary.cpp b/src/Cluster/Cmatrix_Binary.cpp new file mode 100644 index 0000000000..df080719f8 --- /dev/null +++ b/src/Cluster/Cmatrix_Binary.cpp @@ -0,0 +1,188 @@ +#include "Cmatrix_Binary.h" +#include "Cframes.h" +#include "../CpptrajStdio.h" + +Cpptraj::Cluster::Cmatrix_Binary::Cmatrix_Binary() : + sieve_(0), + actual_nrows_(0), + ntotal_(0), + headerOffset_(0) +{} + +// NOTES: +// Version 1: Add write of ignore array when reduced. Write nrows and +// and nelements as 8 byte integers. +// Version 2: Instead of nrows and nelements, write original nrows +// and actual nrows to easily determine if this is a reduced +// matrix. Also write sieve value. +// Version 2 Update: Read/write sieve value as signed, negative +// value is random sieve. Variable is same # +// of bytes so should be backwards-compatible. +const unsigned char Cpptraj::Cluster::Cmatrix_Binary::Magic_[4] = {'C', 'T', 'M', 2}; + +/** File must be set up read. */ +bool Cpptraj::Cluster::Cmatrix_Binary::ID_Cmatrix(CpptrajFile& infile) +{ + unsigned char magic[4]; + + if (infile.OpenFile()) return false; + infile.Read( magic, 4 ); + infile.CloseFile(); + return (magic[0]==Magic_[0] && magic[1]==Magic_[1] && magic[2]==Magic_[2]); +} + +int Cpptraj::Cluster::Cmatrix_Binary::OpenCmatrixRead(FileName const& fname) +{ + unsigned char magic[4]; + uint_8 ROWS, ELTS; + sint_8 SIEVE; + sieve_ = 1; + actual_nrows_ = 0; + + // Open file for reading + if (file_.OpenRead(fname)) { + mprinterr("Error: Could not open '%s' for read.\n", fname.full()); + return 1; + } + // SANITY CHECK: Read and check magic byte + file_.Read( magic, 4 ); + if ( magic[0]!=Magic_[0] || magic[1]!=Magic_[1] || magic[2]!=Magic_[2] ) { + mprinterr("Error: File '%s' is not a Cpptraj Cluster Matrix file.\n", fname.full()); + return 1; + } + // Check version, read in nrows and nelements. + if (magic[3] == 0) { + int Ntemp = 0; + file_.Read( &Ntemp, sizeof(int) ); + ROWS = (uint_8)Ntemp; + actual_nrows_ = (size_t)ROWS; + file_.Read( &Ntemp, sizeof(int) ); + ELTS = (uint_8)Ntemp; + } else if (magic[3] == 1) { + file_.Read( &ROWS, sizeof(uint_8) ); + actual_nrows_ = (size_t)ROWS; + file_.Read( &ELTS, sizeof(uint_8) ); + } else if (magic[3] == 2) { + file_.Read( &ROWS, sizeof(uint_8) ); // V2: Original Nrows + file_.Read( &ELTS, sizeof(uint_8) ); // V2: Actual Nrows + actual_nrows_ = (size_t)ELTS; + file_.Read( &SIEVE, sizeof(sint_8) ); // V2: Sieve + sieve_ = (int)SIEVE; + } else { + mprinterr("Error: ClusterMatrix version %u is not recognized.\n", (unsigned int)magic[3]); + return 1; + } + // Save current header position + headerOffset_ = file_.Tell(); + // Checks + if (magic[3] == 0 || magic[3] == 1) { + // Version 0/1: Actual # of rows is not known yet. Check that the # elements + // in the file match the original # elements (i.e. matrix is not sieved). + // If it is sieved this is not supported. + uint_8 original_nelements = ( ROWS * (ROWS - 1UL) ) / 2UL; + if ( original_nelements != ELTS ) { + mprinterr("Error: Sieved data in ClusterMatrix file %s (version %u) not supported.\n", + fname.full(), (unsigned int)magic[3]); + return 1; + } + sieve_ = 1; + } + ntotal_ = (size_t)ROWS; + return 0; +} + +static long int calcTriIndex(size_t nX, size_t xIn, size_t yIn) { + size_t i, j; + if (yIn > xIn) { + i = xIn; + j = yIn; + } else if (xIn > yIn) { + i = yIn; + j = xIn; + } else // iIn == jIn, triangle matrix diagonal is indicated by -1 + return -1L; + size_t i1 = i + 1UL; + return (long int)(( (nX * i) - ((i1 * i) / 2UL) ) + j - i1); +} + +double Cpptraj::Cluster::Cmatrix_Binary::GetCmatrixElement(unsigned int col, unsigned int row) +{ + // Determine absolute index + long int idx = calcTriIndex(actual_nrows_, col, row); + file_.Seek( headerOffset_ + idx * sizeof(float) ); + float fvar; + file_.Read( &fvar, sizeof(float) ); + return (double)fvar; +} + +double Cpptraj::Cluster::Cmatrix_Binary::GetCmatrixElement(unsigned int idx) +{ + file_.Seek( headerOffset_ + idx * sizeof(float) ); + float fvar; + file_.Read( &fvar, sizeof(float) ); + return (double)fvar; +} + +static inline size_t Nelements(size_t nrows) { + return ( nrows * (nrows - 1UL) ) / 2UL; +} + +int Cpptraj::Cluster::Cmatrix_Binary::GetCmatrix(float* ptr, char* frameIsPresent) { + file_.Seek( headerOffset_ ); + size_t nelements = Nelements( actual_nrows_ ); + if (file_.Read( ptr, nelements * sizeof(float) ) < 1) return 1; + // Read sieve if needed + if (frameIsPresent != 0) { + if (file_.Read( frameIsPresent, ntotal_ * sizeof(char) ) < 1) return 1; + } + return 0; +} + +int Cpptraj::Cluster::Cmatrix_Binary::WriteCmatrix(FileName const& fname, + const float* ptr, + Cframes const& frameToIdx, + size_t Nrows, + int sieveValue) +{ + CpptrajFile outfile; + uint_8 ntemp; + // No stdout write allowed. + if (fname.empty()) { + mprinterr("Internal Error: DataIO_Cmatrix::WriteData() called with no filename.\n"); + return 1; + } + if (outfile.OpenWrite(fname)) { + mprinterr("Error: Could not open %s for write.\n", fname.full()); + return 1; + } + size_t OriginalNframes = frameToIdx.size(); + // Write magic byte + outfile.Write( Magic_, 4 ); + // Write original number of frames. + ntemp = (uint_8)OriginalNframes; + outfile.Write( &ntemp, sizeof(uint_8) ); + // Write actual nrows + ntemp = (uint_8)Nrows; + outfile.Write( &ntemp, sizeof(uint_8) ); + // Write out sieve value + sint_8 stemp = (sint_8)sieveValue; + outfile.Write( &stemp, sizeof(sint_8) ); + // Write matrix elements + size_t nelements = Nelements( Nrows ); + outfile.Write( ptr, nelements*sizeof(float) ); + // If this is a reduced matrix, write whether each frame was sieved (T) or not (F). + // NOTE: definitions are in DataSet_PairwiseCache.h + if (sieveValue != 1) { + //DataSet_PairwiseMatrix::StatusArray frameIsPresent; + std::vector frameIsPresent; + frameIsPresent.reserve( OriginalNframes ); + for (Cframes::const_iterator it = frameToIdx.begin(); + it != frameToIdx.end(); ++it) + if (*it == -1) + frameIsPresent.push_back( 'T' ); + else + frameIsPresent.push_back( 'F' ); + outfile.Write( &frameIsPresent[0], OriginalNframes*sizeof(char) ); + } + return 0; +} diff --git a/src/Cluster/Cmatrix_Binary.h b/src/Cluster/Cmatrix_Binary.h new file mode 100644 index 0000000000..3b7540e83c --- /dev/null +++ b/src/Cluster/Cmatrix_Binary.h @@ -0,0 +1,51 @@ +#ifndef INC_CLUSTER_CMATRIX_BINARY_H +#define INC_CLUSTER_CMATRIX_BINARY_H +#include // size_t +#include "../CpptrajFile.h" +class FileName; +namespace Cpptraj { +namespace Cluster { +class Cframes; +/// Used to read pairwise distance cache files in cpptraj binary format. +class Cmatrix_Binary { + public: + Cmatrix_Binary(); + + /// \return true if file is binary cpptraj cluster matrix file. + static bool ID_Cmatrix(CpptrajFile&); + + /// \return Sieve value. + int Sieve() const { return sieve_; } + /// \return Actual number of rows in matrix. + size_t ActualNrows() const { return actual_nrows_; } + /// \return Number of total frames originally. + size_t Ntotal() const { return ntotal_;} + + /// Open cluster matrix file for reading. Set sieve and actual # rows. + int OpenCmatrixRead(FileName const&); + /// Get cluster matrix element (col, row) + double GetCmatrixElement(unsigned int, unsigned int); + /// Get cluster matrix element (raw index) + double GetCmatrixElement(unsigned int); + /// Read cmatrix into given pointer TODO should this take Matrix/StatusArray? + int GetCmatrix(float*, char*); + + /// Write cluster matrix TODO add a setup routine + static int WriteCmatrix(FileName const&, const float*, Cframes const&, size_t, int); + private: + static const unsigned char Magic_[]; + /// For reading/writing 8 byte unsigned integers + typedef unsigned long long int uint_8; + /// For reading/writing 8 byte signed integers + typedef long long int sint_8; + + CpptrajFile file_; + int sieve_; + size_t actual_nrows_; + size_t ntotal_; ///< Total number of frames in original data. + off_t headerOffset_; +}; + +} +} +#endif diff --git a/src/NC_Cmatrix.cpp b/src/Cluster/Cmatrix_NC.cpp similarity index 79% rename from src/NC_Cmatrix.cpp rename to src/Cluster/Cmatrix_NC.cpp index 0c471c1a62..3a08929cc4 100644 --- a/src/NC_Cmatrix.cpp +++ b/src/Cluster/Cmatrix_NC.cpp @@ -1,13 +1,15 @@ +#include "Cmatrix_NC.h" #ifdef BINTRAJ # include -# include "NC_Routines.h" +# include "../NC_Routines.h" +# include "Cframes.h" #endif -#include "NC_Cmatrix.h" -#include "CpptrajStdio.h" +#include "../CpptrajStdio.h" +#include "../FileName.h" #ifdef BINTRAJ /// CONSTRUCTOR -NC_Cmatrix::NC_Cmatrix() : +Cpptraj::Cluster::Cmatrix_NC::Cmatrix_NC() : ncid_(-1), n_original_frames_DID_(-1), n_rows_DID_(-1), @@ -20,17 +22,24 @@ NC_Cmatrix::NC_Cmatrix() : mode_(READ) {} -NC_Cmatrix::~NC_Cmatrix() { +/// DESTRUCTOR +Cpptraj::Cluster::Cmatrix_NC::~Cmatrix_NC() { CloseCmatrix(); } -bool NC_Cmatrix::IsCpptrajCmatrix(int NCID) { +/** \return true if NetCDF file has CPPTRAJ_CMATRIX conventions. */ +bool Cpptraj::Cluster::Cmatrix_NC::IsCpptrajCmatrix(int NCID) { return (NC::GetAttrText(NCID, "Conventions") == "CPPTRAJ_CMATRIX"); } + +#else /* BINTRAJ */ +Cpptraj::Cluster::Cmatrix_NC::Cmatrix_NC() {} +Cpptraj::Cluster::Cmatrix_NC::~Cmatrix_NC() {} #endif // NC_Cmatrix::ID_Cmatrix() -bool NC_Cmatrix::ID_Cmatrix(FileName const& fname) { +/** \return True if the file specified by name is a NetCDF cluxtre matrix file. */ +bool Cpptraj::Cluster::Cmatrix_NC::ID_Cmatrix(FileName const& fname) { # ifdef BINTRAJ int NCID; if ( nc_open( fname.full(), NC_NOWRITE, &NCID ) != NC_NOERR ) @@ -44,6 +53,11 @@ bool NC_Cmatrix::ID_Cmatrix(FileName const& fname) { # endif } +/** \return estimated matrix disk usage in bytes for given number of rows. */ +size_t Cpptraj::Cluster::Cmatrix_NC::EstimatedDiskUsageInBytes(size_t sizeIn) { + return ((sizeIn*(sizeIn-1))/2)*sizeof(float); +} + #ifdef BINTRAJ // DEFINES #define NC_CMATRIX_NFRAMES "n_original_frames" @@ -54,7 +68,7 @@ bool NC_Cmatrix::ID_Cmatrix(FileName const& fname) { #define NC_CMATRIX_FRAMES "actual_frames" // NC_Cmatrix::OpenCmatrixRead() -int NC_Cmatrix::OpenCmatrixRead(FileName const& fname, int& sieve) { +int Cpptraj::Cluster::Cmatrix_NC::OpenCmatrixRead(FileName const& fname, int& sieve) { if (ncid_ != -1) CloseCmatrix(); if (fname.empty()) return 1; if (NC::CheckErr( nc_open( fname.full(), NC_NOWRITE, &ncid_ ) )) @@ -114,7 +128,7 @@ int NC_Cmatrix::OpenCmatrixRead(FileName const& fname, int& sieve) { // NC_Cmatrix::CalcIndex() // TODO Consolidate code in Matrix.h? -long int NC_Cmatrix::CalcIndex(unsigned int xIn, unsigned int yIn) const { +long int Cpptraj::Cluster::Cmatrix_NC::CalcIndex(unsigned int xIn, unsigned int yIn) const { // Calculate upper-triangle matrix index unsigned int i, j; if (yIn > xIn) { @@ -132,7 +146,7 @@ long int NC_Cmatrix::CalcIndex(unsigned int xIn, unsigned int yIn) const { } // NC_Cmatrix::GetCmatrixElement() -double NC_Cmatrix::GetCmatrixElement(unsigned int xIn, unsigned int yIn) const { +double Cpptraj::Cluster::Cmatrix_NC::GetCmatrixElement(unsigned int xIn, unsigned int yIn) const { float fval; size_t index[1]; long int idx = CalcIndex(xIn, yIn); @@ -144,7 +158,7 @@ double NC_Cmatrix::GetCmatrixElement(unsigned int xIn, unsigned int yIn) const { } // NC_Cmatrix::GetCmatrixElement() -double NC_Cmatrix::GetCmatrixElement(unsigned int idxIn) const { +double Cpptraj::Cluster::Cmatrix_NC::GetCmatrixElement(unsigned int idxIn) const { float fval; size_t index[1] = { idxIn }; if (NC::CheckErr( nc_get_var1_float(ncid_, cmatrix_VID_, index, &fval) )) @@ -153,7 +167,7 @@ double NC_Cmatrix::GetCmatrixElement(unsigned int idxIn) const { } // NC_Cmatrix::GetSieveStatus() -std::vector NC_Cmatrix::GetSieveStatus() const { +std::vector Cpptraj::Cluster::Cmatrix_NC::GetSieveStatus() const { if (nFrames_ < 1) return std::vector(); if (actualFrames_VID_ == -1) // No frames array. All frames present, none sieved. @@ -175,7 +189,7 @@ std::vector NC_Cmatrix::GetSieveStatus() const { } // NC_Cmatrix::GetCmatrix() -int NC_Cmatrix::GetCmatrix(float* ptr) const { +int Cpptraj::Cluster::Cmatrix_NC::GetCmatrix(float* ptr) const { if (cmatrix_VID_ == -1) return 1; size_t start[1] = { 0 }; size_t count[1] = { mSize_ }; @@ -183,8 +197,9 @@ int NC_Cmatrix::GetCmatrix(float* ptr) const { } // NC_Cmatrix::CreateCmatrix() -int NC_Cmatrix::CreateCmatrix(FileName const& fname, unsigned int nFramesIn, unsigned int nRowsIn, - int sieve, std::string const& metricDescripIn) +int Cpptraj::Cluster::Cmatrix_NC::CreateCmatrix(FileName const& fname, unsigned int nFramesIn, + unsigned int nRowsIn, + int sieve, std::string const& metricDescripIn) { //mprinterr("DEBUG: Cmatrix file '%s', nFrames %u, nRows %u, sieve %i\n", // fname.full(), nFrames, nRowsIn, sieve); @@ -262,12 +277,12 @@ int NC_Cmatrix::CreateCmatrix(FileName const& fname, unsigned int nFramesIn, uns } // NC_Cmatrix::Sync() -void NC_Cmatrix::Sync() const { +void Cpptraj::Cluster::Cmatrix_NC::Sync() const { if (ncid_ != -1) NC::CheckErr( nc_sync(ncid_) ); } -int NC_Cmatrix::ReopenSharedWrite(FileName const& fname) { +int Cpptraj::Cluster::Cmatrix_NC::ReopenSharedWrite(FileName const& fname) { if (ncid_ == -1) return 1; // Close and re-open shared nc_close( ncid_ ); @@ -276,7 +291,7 @@ int NC_Cmatrix::ReopenSharedWrite(FileName const& fname) { } // NC_Cmatrix::WriteFramesArray() -int NC_Cmatrix::WriteFramesArray(std::vector const& actualFrames) const { +int Cpptraj::Cluster::Cmatrix_NC::WriteFramesArray(std::vector const& actualFrames) const { if (ncid_ == -1) return 1; // Sanity check if (actualFrames_VID_ == -1) { mprinterr("Error: No cluster frames variable ID defined.\n"); @@ -294,8 +309,16 @@ int NC_Cmatrix::WriteFramesArray(std::vector const& actualFrames) const { return 0; } +int Cpptraj::Cluster::Cmatrix_NC::WriteFramesArray(Cpptraj::Cluster::Cframes const& actualFrames) +const +{ + // TODO have Cframes return a pointer? + return WriteFramesArray(actualFrames.Data()); +} + // NC_Cmatrix::WriteCmatrixElement() -int NC_Cmatrix::WriteCmatrixElement(unsigned int xIn, unsigned int yIn, double dval) const +int Cpptraj::Cluster::Cmatrix_NC::WriteCmatrixElement(unsigned int xIn, unsigned int yIn, + double dval) const { int err = 0; # ifdef _OPENMP @@ -321,7 +344,7 @@ int NC_Cmatrix::WriteCmatrixElement(unsigned int xIn, unsigned int yIn, double d } // NC_Cmatrix::WriteCmatrix() -int NC_Cmatrix::WriteCmatrix(const float* ptr) const { +int Cpptraj::Cluster::Cmatrix_NC::WriteCmatrix(const float* ptr) const { if (cmatrix_VID_ == -1) return 1; size_t start[1] = { 0 }; size_t count[1] = { mSize_ }; @@ -329,30 +352,11 @@ int NC_Cmatrix::WriteCmatrix(const float* ptr) const { } // NC_Cmatrix::CloseCmatrix() -void NC_Cmatrix::CloseCmatrix() { +void Cpptraj::Cluster::Cmatrix_NC::CloseCmatrix() { if (ncid_ != -1) { nc_close( ncid_ ); ncid_ = -1; // TODO: Set all IDs to -1 too? } } -#else -NC_Cmatrix::NC_Cmatrix() {} -NC_Cmatrix::~NC_Cmatrix() {} -int NC_Cmatrix::OpenCmatrixRead(FileName const&, int&) { return 1; } -double NC_Cmatrix::GetCmatrixElement(unsigned int, unsigned int) const { return 0.0; } -double NC_Cmatrix::GetCmatrixElement(unsigned int) const { return 0.0; } -std::vector NC_Cmatrix::GetSieveStatus() const { return std::vector(); } -int NC_Cmatrix::GetCmatrix(float*) const { return 1; } -int NC_Cmatrix::CreateCmatrix(FileName const&, unsigned int, unsigned int, int, std::string const&) -{ - mprinterr("Error: Cpptraj was compiled without NetCDF. Cannot create NetCDF matrix file.\n"); - return 1; -} -int NC_Cmatrix::WriteFramesArray(std::vector const&) const { return 1; } -int NC_Cmatrix::WriteCmatrixElement(unsigned int, unsigned int, double) const { return 1; } -int NC_Cmatrix::WriteCmatrix(const float*) const { return 1; } -void NC_Cmatrix::CloseCmatrix() {} -void NC_Cmatrix::Sync() const {} -int NC_Cmatrix::ReopenSharedWrite(FileName const&) { return 1; } -#endif +#endif /* BINTRAJ */ diff --git a/src/NC_Cmatrix.h b/src/Cluster/Cmatrix_NC.h similarity index 82% rename from src/NC_Cmatrix.h rename to src/Cluster/Cmatrix_NC.h index 284a130e32..951dff95ba 100644 --- a/src/NC_Cmatrix.h +++ b/src/Cluster/Cmatrix_NC.h @@ -1,14 +1,23 @@ -#ifndef INC_NC_CMATRIX_H -#define INC_NC_CMATRIX_H -#include "FileName.h" +#ifndef INC_CLUSTER_CMATRIX_NC_H +#define INC_CLUSTER_CMATRIX_NC_H +#include +#include +class FileName; +namespace Cpptraj { +namespace Cluster { +class Cframes; /// NetCDF cluster matrix file. -class NC_Cmatrix { +class Cmatrix_NC { public: enum ModeType { READ=0, WRITE }; - NC_Cmatrix(); - ~NC_Cmatrix(); + Cmatrix_NC(); + ~Cmatrix_NC(); + /// \return Estimated disk usage in bytes for given # rows + static size_t EstimatedDiskUsageInBytes(size_t); /// \return true if file is NetCDF cluster matrix file. static bool ID_Cmatrix(FileName const&); + +# ifdef BINTRAJ /// Open cluster matrix file for reading. Set sieve ID. int OpenCmatrixRead(FileName const&, int&); /// Get cluster matrix element (col, row) @@ -26,25 +35,22 @@ class NC_Cmatrix { /// Reopen in shared write mode for random access int ReopenSharedWrite(FileName const&); /// Write non-sieved frames array. - int WriteFramesArray(std::vector const&) const; + int WriteFramesArray(std::vector const&) const; // TODO deprecate + int WriteFramesArray(Cframes const&) const; /// Write cluster matrix element (col, row) int WriteCmatrixElement(unsigned int, unsigned int, double) const; /// Write cluster matrix using given pointer int WriteCmatrix(const float*) const; /// Close cluster matrix file. void CloseCmatrix(); -# ifdef BINTRAJ + /// \return Matrix size unsigned int MatrixSize() const { return mSize_; } /// \return Matrix rows. unsigned int MatrixRows() const { return nRows_; } /// \return Current access mode ModeType Mode() const { return mode_; } -# else - unsigned int MatrixSize() const { return 0; } - unsigned int MatrixRows() const { return 0; } - ModeType Mode() const { return READ; } -# endif +# endif /* BINTRAJ */ private: # ifdef BINTRAJ static inline bool IsCpptrajCmatrix(int); @@ -60,6 +66,9 @@ class NC_Cmatrix { unsigned int nRows_; ///< Number of rows (actual frames, N) in matrix dimension. unsigned int mSize_; ///< Actual matrix size. ModeType mode_; ///< Access mode. -# endif +# endif /* BINTRAJ */ }; + +} +} #endif diff --git a/src/Cluster/Control.cpp b/src/Cluster/Control.cpp new file mode 100644 index 0000000000..c596b327f3 --- /dev/null +++ b/src/Cluster/Control.cpp @@ -0,0 +1,937 @@ +#include "Control.h" +#include "Output.h" +#include "../ArgList.h" +#include "../BufferedLine.h" // For loading info file +#include "../CpptrajStdio.h" +#include "../DataFile.h" // For loading pairwise cache +#include "../DataFileList.h" +#include "../DataSet_Coords.h" +#include "../DataSet_float.h" +#include "../DataSet_integer.h" +#include "../DataSet_PairwiseCache.h" +// Algorithms +#include "Algorithm_HierAgglo.h" +#include "Algorithm_DBscan.h" +#include "Algorithm_Kmeans.h" +#include "Algorithm_DPeaks.h" +// Results +#include "Results_Coords.h" + +/** CONSTRUCTOR */ +Cpptraj::Cluster::Control::Control() : + algorithm_(0), + results_(0), + verbose_(0), + frameSelect_(UNSPECIFIED), + sieve_(1), + sieveSeed_(-1), + sieveRestore_(NO_RESTORE), + restoreEpsilon_(0.0), + includeSieveInCalc_(false), + includeSieveCdist_(false), + bestRep_(BestReps::NO_REPS), + nRepsToSave_(1), + suppressInfo_(false), + cnumvtime_(0), + grace_color_(false), + clustersVtime_(0), + windowSize_(0), + cpopvtimefile_(0), + norm_pop_(Node::NONE), + calc_lifetimes_(false), + drawGraph_(NO_DRAWGRAPH), + draw_tol_(0), + draw_maxit_(0), + debug_(0), + metricContribFile_(0) +{} + +/** DESTRUCTOR */ +Cpptraj::Cluster::Control::~Control() { + if (algorithm_ != 0) delete algorithm_; + if (results_ != 0 ) delete results_; +} + +// ----------------------------------------------------------------------------- +/** \return Pointer to Algorithm of given type. */ +Cpptraj::Cluster::Algorithm* Cpptraj::Cluster::Control::AllocateAlgorithm(Algorithm::AType atype) +{ + Algorithm* alg = 0; + switch (atype) { + case Algorithm::HIERAGGLO : alg = new Algorithm_HierAgglo(); break; + case Algorithm::DBSCAN : alg = new Algorithm_DBscan(); break; + case Algorithm::KMEANS : alg = new Algorithm_Kmeans(); break; + case Algorithm::DPEAKS : alg = new Algorithm_DPeaks(); break; + default : mprinterr("Error: Unhandled Algorithm in AllocateAlgorithm.\n"); + } + return alg; +} + +/** Recognized algorithm keywords. */ +const char* Cpptraj::Cluster::Control::AlgorithmArgs_ = + "{hieragglo|dbscan|kmeans|dpeaks}"; + +/** Set up Algorithm from keyword + arguments. */ +int Cpptraj::Cluster::Control::AllocateAlgorithm(ArgList& analyzeArgs) { + Algorithm::AType atype = Algorithm::UNSPECIFIED; + if (analyzeArgs.hasKey("hieragglo")) atype = Algorithm::HIERAGGLO; + else if (analyzeArgs.hasKey("dbscan" )) atype = Algorithm::DBSCAN; + else if (analyzeArgs.hasKey("kmeans") || + analyzeArgs.hasKey("means") ) atype = Algorithm::KMEANS; + else if (analyzeArgs.hasKey("dpeaks" )) atype = Algorithm::DPEAKS; + else { + mprintf("Warning: No clustering algorithm specified; defaulting to 'hieragglo'\n"); + atype = Algorithm::HIERAGGLO; + } + if (algorithm_ != 0) delete algorithm_; + algorithm_ = AllocateAlgorithm( atype ); + if (algorithm_ == 0) return 1; + if (algorithm_->Setup( analyzeArgs )) return 1; + return 0; +} + +// ----------------------------------------------------------------------------- +static int Err(int code) { + switch (code) { + case 0: mprinterr("Error: Could not open info file.\n"); break; + case 1: mprinterr("Error: Unexpected end of info file.\n"); break; + case 2: mprinterr("Error: Invalid number of clusters in info file.\n"); break; + case 3: mprinterr("Error: Invalid number of frames in info file.\n"); break; + } + return 1; +} + +/** Read clustering info from existing info file. */ +int Cpptraj::Cluster::Control::ReadInfo(std::string const& fname) { + if (fname.empty()) { + mprinterr("Error: No cluster info filename given.\n"); + return 1; + } + mprintf("\tReading clusters from info file '%s'\n", fname.c_str()); + BufferedLine infile; + if (infile.OpenFileRead( fname )) return Err(0); + const char* ptr = infile.Line(); + if (ptr == 0) return Err(1); + ArgList infoLine( ptr, " " ); + int nclusters = infoLine.getKeyInt("#Clustering:", -1); + if (nclusters == -1) return Err(2); + int nframes = infoLine.getKeyInt("clusters", -1); + if (nframes == -1) return Err(3); + mprintf("\tNumber of frames in info file: %i\n", nframes); +// if (nframes != (int)FrameDistances().OriginalNframes()) { +// mprinterr("Error: # frames in cluster info file (%i) does not match" +// " current # frames (%zu)\n", nframes, FrameDistances().OriginalNframes()); +// return 1; +// } + // Scan down to clusters + std::string algorithmStr; + while (ptr[0] == '#') { + ptr = infile.Line(); + if (ptr == 0) return Err(1); + // Save previous clustering info. Includes newline. + if (ptr[1] == 'A' && ptr[2] == 'l' && ptr[3] == 'g') + algorithmStr.assign( ptr + 12 ); // Right past '#Algorithm: ' + } + if (!algorithmStr.empty()) mprintf("\tAlgorithm in info file: %s\n", algorithmStr.c_str()); + // Read clusters + Cframes frames; + for (int cnum = 0; cnum != nclusters; cnum++) { + if (ptr == 0) return Err(1); + frames.clear(); + // TODO: Check for busted lines? + for (int fidx = 0; fidx != nframes; fidx++) { + if (ptr[fidx] == 'X') + frames.push_back( fidx ); + } + clusters_.AddCluster( Node(metrics_, frames, cnum) ); + mprintf("\tRead cluster %i, %zu frames.\n", cnum, frames.size()); + ptr = infile.Line(); + } + infile.CloseFile(); + return 0; +} + +/** Set up clusters from a cluster number vs time data set. */ +int Cpptraj::Cluster::Control::InitClustersFromSet(DataSet* cnvt) { + if (cnvt == 0) { + mprinterr("Internal Error: InitClustersFromSet: Null set.\n"); + return 1; + } + mprintf("\tReading clusters from cluster num vs time set '%s'\n", cnvt->legend()); + if (cnvt->Group() != DataSet::SCALAR_1D) { + mprinterr("Error: Set '%s' is not a scalar 1D set.\n", cnvt->legend()); + return 1; + } + if (cnvt->Type() != DataSet::INTEGER) { + mprintf("Warning: Set '%s' is not an integer set. Floating point values\n" + "Warning: will be rounded to integer values.\n", cnvt->legend()); + } + // Hold frames for each cluster + std::vector clusterFrames; + DataSet_1D const& ds = static_cast( *cnvt ); + for (unsigned int idx = 0; idx != cnvt->Size(); idx++) + { + int cnum = ds.Dval(idx); + if (cnum > -1) { + if (cnum >= (int)clusterFrames.size()) { + while ((int)clusterFrames.size() <= cnum) + clusterFrames.push_back( Cframes() ); + } + clusterFrames[cnum].push_back( (int)idx ); + } + } + int clusterNum = 0; + for (std::vector::const_iterator frames = clusterFrames.begin(); + frames != clusterFrames.end(); + ++frames, ++clusterNum) + clusters_.AddCluster( Node(metrics_, *frames, clusterNum) ); + return 0; +} + +// ----------------------------------------------------------------------------- + +const char* Cpptraj::Cluster::Control::SieveArgs1_ = + "[sieve <#> [sieveseed <#>] [random] [includesieveincalc] [includesieved_cdist]"; + +const char* Cpptraj::Cluster::Control::SieveArgs2_ = + " [{sievetoframe|sievetocentroid|closestcentroid}] [repsilon ]]"; + +const char* Cpptraj::Cluster::Control::BestRepArgs_ = + "[bestrep {cumulative|centroid|cumulative_nosieve}] [savenreps <#>]"; + +const char* Cpptraj::Cluster::Control::OutputArgs1_ = + "[out [gracecolor]] [noinfo|info ] [summary ]"; + +const char* Cpptraj::Cluster::Control::OutputArgs2_ = + "[summarysplit ] [splitframe ]"; + +const char* Cpptraj::Cluster::Control::OutputArgs3_ = + "[clustersvtime [cvtwindow <#>]] [sil ] [metricstats ]"; + +const char* Cpptraj::Cluster::Control::OutputArgs4_ = + "[cpopvtime [{normpop|normframe}]] [lifetime]"; + +const char* Cpptraj::Cluster::Control::GraphArgs_ = + "[{drawgraph|drawgraph3d} [draw_tol ] [draw_maxit ( coordsSet ) ); + if (results_ == 0) return 1; + if (results_->GetOptions(analyzeArgs, DSL, metrics_)) return 1; + } + + // Allocate algorithm + if (AllocateAlgorithm( analyzeArgs )) { + mprinterr("Error: Algorithm setup failed.\n"); + return 1; + } + algorithm_->SetDebug( verbose_ ); + + // Sieve options + sieveSeed_ = analyzeArgs.getKeyInt("sieveseed", -1); + sieve_ = analyzeArgs.getKeyInt("sieve", 1); + if (sieve_ < 1) { + mprinterr("Error: 'sieve <#>' must be >= 1 (%i)\n", sieve_); + return 1; + } + if (analyzeArgs.hasKey("random") && sieve_ > 1) + sieve_ = -sieve_; // negative # indicates random sieve + + // TODO incorporate with cumulative_nosieve? Or keep granular? + includeSieveInCalc_ = analyzeArgs.hasKey("includesieveincalc"); + if (includeSieveInCalc_) + mprintf("Warning: 'includesieveincalc' may be very slow.\n"); + includeSieveCdist_ = analyzeArgs.hasKey("includesieved_cdist"); + if (includeSieveCdist_) + mprintf("Warning: 'includesieved_cdist' may be very slow.\n"); + + // Determine how frames to cluster will be chosen + if (frameSelect_ == UNSPECIFIED) { + // If no other frame selection option like sieve provided and an already + // set up cache is present, use the cached frames. + if (sieve_ == 1 && metrics_.HasCache() && metrics_.Cache().Size() > 0) + { + frameSelect_ = FROM_CACHE; + if (metrics_.Cache().SieveVal() != 1) { + sieve_ = metrics_.Cache().SieveVal(); + mprintf("Warning: No sieve specified; using sieve value from cache '%s': %i\n", + metrics_.Cache().legend(), sieve_); + } + } + } + + // Choose sieve restore options + if (sieve_ != 1) + { + // Determine sieve restore type + if (sieveRestore_ == NO_RESTORE) { + // No option set yet. See if a keyword has been specified. + if (analyzeArgs.hasKey("nosieverestore")) // Hidden option, currently for testing only + sieveRestore_ = NO_RESTORE; + else if (analyzeArgs.hasKey("sievetoframe")) + sieveRestore_ = EPSILON_FRAME; + else if (analyzeArgs.hasKey("sievetocentroid")) + sieveRestore_ = EPSILON_CENTROID; + else if (analyzeArgs.hasKey("closestcentroid")) + sieveRestore_ = CLOSEST_CENTROID; + else { + // Nothing specified yet. Choose restore option based on algorithm. + if (algorithm_->Type() == Algorithm::DBSCAN || + algorithm_->Type() == Algorithm::DPEAKS) + sieveRestore_ = EPSILON_CENTROID; + else + sieveRestore_ = CLOSEST_CENTROID; + } + } + // Determine sieve restore epsilon + if (sieveRestore_ == EPSILON_FRAME || + sieveRestore_ == EPSILON_CENTROID) + { + // Epsilon-based sieve restore + if (algorithm_->Type() == Algorithm::DBSCAN || + algorithm_->Type() == Algorithm::DPEAKS) + { + // Using a density-based algorithm with epsilon-based restore; + // use restore epsilon from algorithm. + restoreEpsilon_ = algorithm_->Epsilon(); + } + } + double rEps = analyzeArgs.getKeyDouble("repsilon", -1.0); + if (rEps > 0) + restoreEpsilon_ = rEps; + } + + // Best rep options + std::string bestRepStr = analyzeArgs.GetStringKey("bestrep"); + if (bestRepStr.empty()) { + // For sieving, cumulative can get very expensive. Default to centroid. + if (sieve_ != 1) + bestRep_ = BestReps::CENTROID; + else + bestRep_ = BestReps::CUMULATIVE; + } else { + if (bestRepStr == "cumulative") + bestRep_ = BestReps::CUMULATIVE; + else if (bestRepStr == "centroid") + bestRep_ = BestReps::CENTROID; + else if (bestRepStr == "cumulative_nosieve") + bestRep_ = BestReps::CUMULATIVE_NOSIEVE; + else { + mprinterr("Error: Invalid 'bestRep' option (%s)\n", bestRepStr.c_str()); + return 1; + } + } + nRepsToSave_ = analyzeArgs.getKeyInt("savenreps", 1); + if (nRepsToSave_ < 1) { + mprinterr("Error: 'savenreps' must be > 0\n"); + return 1; + } + + // Draw graph + if (analyzeArgs.hasKey("drawgraph")) + drawGraph_ = TWOD; + else if (analyzeArgs.hasKey("drawgraph3d")) + drawGraph_ = THREED; + else + drawGraph_ = NO_DRAWGRAPH; + draw_maxit_ = analyzeArgs.getKeyInt("draw_maxit", 1000); + draw_tol_ = analyzeArgs.getKeyDouble("draw_tol", 1.0E-5); + + // Cluster info output + suppressInfo_ = analyzeArgs.hasKey("noinfo"); + if (!suppressInfo_) + clusterinfo_ = analyzeArgs.GetStringKey("info"); + + // Cluster summary output + summaryfile_ = analyzeArgs.GetStringKey("summary"); + + // Cluster silhouette output + sil_file_ = analyzeArgs.GetStringKey("sil"); + + // Cluster pop v time output + cpopvtimefile_ = DFL.AddDataFile(analyzeArgs.GetStringKey("cpopvtime"), analyzeArgs); + if (cpopvtimefile_ != 0) { + if (analyzeArgs.hasKey("normpop")) + norm_pop_ = Node::CLUSTERPOP; + else if (analyzeArgs.hasKey("normframe")) + norm_pop_ = Node::FRAME; + else + norm_pop_ = Node::NONE; + } + + // Number of unique clusters vs time + DataFile* clustersvtimefile = DFL.AddDataFile(analyzeArgs.GetStringKey("clustersvtime"), + analyzeArgs); + windowSize_ = analyzeArgs.getKeyInt("cvtwindow", 0); + + // Create cluster lifetime data sets? + calc_lifetimes_ = analyzeArgs.hasKey("lifetime"); + + // Cluster number vs time + grace_color_ = analyzeArgs.hasKey("gracecolor"); + DataFile* cnumvtimefile = DFL.AddDataFile(analyzeArgs.GetStringKey("out"), analyzeArgs); + + // Cluster split analysis + splitfile_ = analyzeArgs.GetStringKey("summarysplit"); + if (splitfile_.empty()) // For backwards compat. + splitfile_ = analyzeArgs.GetStringKey("summaryhalf"); + if (!splitfile_.empty()) { + ArgList splits( analyzeArgs.GetStringKey("splitframe"), "," ); + if (!splits.empty()) { + splitFrames_.clear(); + int sf = splits.getNextInteger(-1); // User frame #s start at 1 + while (sf > 0) { + splitFrames_.push_back( sf ); + sf = splits.getNextInteger(-1); + } + if ((int)splitFrames_.size() < splits.Nargs()) { + mprinterr("Error: Invalid split frame arguments.\n"); + splits.CheckForMoreArgs(); + return 1; + } + } + } + + // Overall set name extracted here. All other arguments should already be processed. + dsname_ = analyzeArgs.GetStringNext(); + if (dsname_.empty()) + dsname_ = DSL.GenerateDefaultName("CLUSTER"); + // --------------------------------------------- + + // Cluster number vs time data set + cnumvtime_ = DSL.AddSet(DataSet::INTEGER, dsname_, "Cnum"); + if (cnumvtime_ == 0) return 1; + if (cnumvtimefile != 0) cnumvtimefile->AddDataSet( cnumvtime_ ); + + // If cache was allocated, add to the DataSetList so it is after cnumvtime for pytraj + if (metrics_.CacheWasAllocated()) + DSL.AddSet( metrics_.CachePtr() ); + + // Set up number of unique clusters vs time DataSet + if (clustersvtimefile != 0) { + if (windowSize_ < 2) { + mprinterr("Error: For # clusters seen vs time, cvtwindow must be specified and > 1\n"); + return 1; + } + clustersVtime_ = DSL.AddSet(DataSet::INTEGER, MetaData(cnumvtime_->Meta().Name(), "NCVT")); + if (clustersVtime_ == 0) return 1; + clustersvtimefile->AddDataSet( clustersVtime_ ); + } + + return 0; +} + +/** Print help text to STDOUT. */ +void Cpptraj::Cluster::Control::Help() { + mprintf("\t[] [] [] [] [] []\n" + "\t[] [] []\n" + "\t[readinfo {infofile | cnvtset }]\n"); + mprintf(" Algorithm Args: [%s]\n", AlgorithmArgs_); + Algorithm_HierAgglo::Help(); + Algorithm_DBscan::Help(); + Algorithm_Kmeans::Help(); + Algorithm_DPeaks::Help(); + mprintf(" Metric Args:\n"); + mprintf("\t%s\n", MetricArray::MetricArgs_); + mprintf(" Pairwise Args:\n"); + mprintf("\t%s\n", MetricArray::PairwiseArgs1_); + mprintf("\t%s\n", MetricArray::PairwiseArgs2_); + mprintf(" Sieve Args:\n"); + mprintf("\t%s\n", SieveArgs1_); + mprintf("\t%s\n", SieveArgs2_); + mprintf(" BestRep Args:\n"); + mprintf("\t%s\n", BestRepArgs_); + mprintf(" Output Args:\n"); + mprintf("\t%s\n", OutputArgs1_); + mprintf("\t%s\n", OutputArgs2_); + mprintf("\t%s\n", OutputArgs3_); + mprintf("\t%s\n", OutputArgs4_); + mprintf(" Coordinate Output Args:\n"); + Results_Coords::Help(); + mprintf(" Graph Args:\n"); + mprintf("\t%s\n", GraphArgs_); + mprintf(" Cluster the data from given input data set(s) (currently any combination\n" + " of COORDS and 1D sets are supported) using the specified clustering\n" + " algorithm. If any input sets are COORDS sets, the metric used to calculate\n" + " frame-frame distances can also be specified (default RMSD).\n" + " In order to speed up clustering of large sets, the 'sieve' keyword can be\n" + " used to cluster a subset of the data, after which the remaining frames\n" + " are added back in. In addition, subsequent clustering calculations can be\n" + " sped up by writing to/reading from a pair-wise distance cache file/DataSet\n" + " specified by 'pairdist'.\n"); +} + +// ----------------------------------------------------------------------------- +void Cpptraj::Cluster::Control::Info() const { + metrics_.Info(); + if (metricContribFile_ != 0) + mprintf("\tContributions of each metric to the total distance will be printed to '%s'.\n", + metricContribFile_->Filename().full()); + + if (algorithm_ != 0) algorithm_->Info(); + + if (results_ != 0) + results_->Info(); + else + mprintf("\tNo coordinates set provided for cluster results.\n"); + + if (frameSelect_ == FROM_CACHE) { + mprintf("\tWill cluster frames present in existing pairwise cache '%s'\n", + metrics_.Cache().legend()); + } else { + if (sieve_ > 1) + mprintf("\tInitial clustering sieve value is %i frames.\n", sieve_); + else if (sieve_ < -1) { + mprintf("\tInitial clustering will be randomly sieved (with value %i)", -sieve_); + if (sieveSeed_ > 0) mprintf(" using random seed %i", sieveSeed_); + mprintf(".\n"); + } + } + + if (sieveRestore_ != NO_RESTORE) { + mprintf("\tRestoring sieved frames"); + if (sieveRestore_ == CLOSEST_CENTROID) + mprintf(" by closest distance to centroid.\n"); + else if (sieveRestore_ == EPSILON_CENTROID) + mprintf(" if within epsilon %f of a centroid (less accurate but faster).\n", restoreEpsilon_); + else if (sieveRestore_ == EPSILON_FRAME) + mprintf(" if within epsilon %f of a frame (more accurate and identifies noise but slower).\n", restoreEpsilon_); + } + + mprintf("\tRepresentative frames will be chosen by"); + switch (bestRep_) { + case BestReps::CUMULATIVE: mprintf(" lowest cumulative distance to all other frames.\n"); break; + case BestReps::CENTROID : mprintf(" closest distance to cluster centroid.\n"); break; + case BestReps::CUMULATIVE_NOSIEVE: + mprintf(" lowest cumulative distance to all other frames (ignore sieved frames).\n"); + break; + default: // sanity check + mprintf("\n"); + } + if (nRepsToSave_ > 1) + mprintf("\tThe top %i representative frames will be determined.\n", nRepsToSave_); + + if (!clusterinfo_.empty()) + mprintf("\tCluster information will be written to %s\n",clusterinfo_.c_str()); + if (!summaryfile_.empty()) { + mprintf("\tSummary of cluster results will be written to %s\n",summaryfile_.c_str()); + if (sieve_ != 1) { + if (includeSieveInCalc_) + mprintf("\tInternal cluster averages will include sieved frames.\n"); + if (includeSieveCdist_) + mprintf("\tBetween-cluster distances will include sieved frames.\n"); + } + } + if (!sil_file_.empty()) { + mprintf("\tFrame silhouettes will be written to %s.frame.dat, cluster silhouettes\n" + "\t will be written to %s.cluster.dat\n", sil_file_.c_str(), sil_file_.c_str()); + if (sieve_ != 1) { + if (includeSieveInCalc_) + mprintf("\tSilhouette calculation will use all frames.\n"); + else + mprintf("\tSilhouette calculation will use non-sieved frames ONLY.\n"); + } + } + + if (cnumvtime_ != 0) { + mprintf("\tCluster number vs time data set: %s\n", cnumvtime_->legend()); + if (grace_color_) + mprintf("\tGrace color instead of cluster number (1-15, 0 = noise) will be saved.\n"); + } + + if (clustersVtime_ != 0) { + mprintf("\tNumber of unique clusters observed over windows of size %i data set: %s\n", + windowSize_, clustersVtime_->legend()); + } + + if (cpopvtimefile_ != 0) { + mprintf("\tCluster pop vs time will be written to %s", cpopvtimefile_->DataFilename().base()); + if (norm_pop_ == Node::CLUSTERPOP) + mprintf(" (normalized by cluster size)"); + else if (norm_pop_ == Node::FRAME) + mprintf(" (normalized by frame)"); + mprintf("\n"); + } + + if (calc_lifetimes_) + mprintf("\tCluster lifetime data sets will be created with aspect 'Lifetime'\n"); + + if (!splitfile_.empty()) { + mprintf("\tSummary comparing parts of trajectory data for clusters will be written to %s\n", + splitfile_.c_str()); + if (!splitFrames_.empty()) { + mprintf("\t\tFrames will be split at:"); + for (std::vector::const_iterator f = splitFrames_.begin(); f != splitFrames_.end(); ++f) + mprintf(" %i", *f); + mprintf("\n"); + } else + mprintf("\t\tFrames will be split at the halfway point.\n"); + } + // TODO loaded refs_ + if (drawGraph_ != NO_DRAWGRAPH) + mprintf("\tEXPERIMENTAL: Force-directed graph will be drawn from pairwise distances.\n" + "\t Max iterations= %i, min tolerance= %g\n", + draw_maxit_, draw_tol_); +} + +/** Figure out which frames to cluster, cache distances if necessary, then + * perform clustering. Afterwards sieved frames will be added in if necessary + * and representative frames will be determined. + */ +int Cpptraj::Cluster::Control::Run() { + if (metrics_.empty() || algorithm_ == 0) { + mprinterr("Internal Error: Cluster::Control is not set up.\n"); + return 1; + } + + // Timers + timer_run_.Start(); + timer_setup_.Start(); + // Set up the Metric + if (metrics_.Setup()) { + mprinterr("Error: Metric setup failed.\n"); + return 1; + } + if (metrics_.Ntotal() < 1) { + mprinterr("Error: No frames to cluster; all input sets are empty.\n"); + return 1; + } + + // Figure out which frames to cluster + frameSieve_.Clear(); + int frameSelectErr = 1; + switch ( frameSelect_ ) { + case UNSPECIFIED: + frameSelectErr = frameSieve_.SetFramesToCluster(sieve_, metrics_.Ntotal(), sieveSeed_); + break; + case FROM_CACHE : + mprintf("\tClustering frames present in pairwise cache '%s'\n", metrics_.Cache().legend()); + frameSelectErr = frameSieve_.SetupFromCache( metrics_.Cache(), metrics_.Ntotal() ); + break; + default : + mprinterr("Internal Error: Cluster::Control::Run(): Unhandled frame selection type.\n"); + } + if (frameSelectErr != 0) { + mprinterr("Error: Cluster frame selection failed.\n"); + return 1; + } + if (verbose_ >= 0) { + if (frameSieve_.FramesToCluster().size() < metrics_.Ntotal()) + mprintf("\tClustering %zu of %u points.\n", frameSieve_.FramesToCluster().size(), + metrics_.Ntotal()); + else + mprintf("\tClustering %u points.\n", metrics_.Ntotal()); + } + Cframes const& framesToCluster = frameSieve_.FramesToCluster(); + + // Calculate contribution to total for each metric + if (metricContribFile_ != 0) + metrics_.CalculateMetricContributions(framesToCluster, *metricContribFile_); + + timer_setup_.Stop(); + timer_pairwise_.Start(); + + // Cache distances if necessary + if (metrics_.CacheDistances( framesToCluster, sieve_ )) return 1; + if (metrics_.HasCache() && verbose_ > 1) + metrics_.Cache().PrintCached(); + + timer_pairwise_.Stop(); + timer_cluster_.Start(); + + // Cluster + if (algorithm_->DoClustering(clusters_, framesToCluster, metrics_) != 0) { + mprinterr("Error: Clustering failed.\n"); + return 1; + } + + timer_cluster_.Stop(); + + // --------------------------------------------- + if (clusters_.Nclusters() == 0) { + mprintf("\tNo clusters found.\n"); + } else { + timer_post_.Start(); + //Timer cluster_post_coords; + timer_post_renumber_.Start(); + // Update cluster centroids here in case they need to be used to + // restore sieved frames + clusters_.UpdateCentroids( metrics_ ); + + // Add sieved frames to existing clusters. + if ( sieveRestore_ != NO_RESTORE ) { + // Restore sieved frames + mprintf("\tRestoring sieved frames.\n"); + switch (sieveRestore_) { + case CLOSEST_CENTROID : + clusters_.AddFramesByCentroid( frameSieve_.SievedOut(), metrics_ ); break; + case EPSILON_CENTROID : + case EPSILON_FRAME : + clusters_.AddFramesByCentroid( frameSieve_.SievedOut(), metrics_, + (sieveRestore_ == EPSILON_CENTROID), + restoreEpsilon_ ); + break; + default: + mprinterr("Internal Error: Unhandled sieve restore type.\n"); + return 1; + } + // Re-calculate the cluster centroids + clusters_.UpdateCentroids( metrics_ ); + } + + // Sort by population and renumber + clusters_.Sort(); + + timer_post_renumber_.Stop(); + timer_post_bestrep_.Start(); + + // Find best representative frames for each cluster. + BestReps findBestReps; + if (findBestReps.InitBestReps(bestRep_, nRepsToSave_, verbose_)) { + mprinterr("Error: Initializing best representative frames search failed.\n"); + return 1; + } + if (findBestReps.FindBestRepFrames(clusters_, metrics_, frameSieve_.SievedOut())) { + mprinterr("Error: Finding best representative frames for clusters failed.\n"); + return 1; + } + + timer_post_bestrep_.Stop(); + + // DEBUG - print clusters to stdout + if (verbose_ > 0) { + mprintf("\nFINAL CLUSTERS:\n"); + clusters_.PrintClusters(); + } + + // TODO assign reference names + } + timer_run_.Stop(); + return 0; +} + +/** Write results to files etc. */ +int Cpptraj::Cluster::Control::Output(DataSetList& DSL) { + if (clusters_.Nclusters() == 0) return 0; + timer_output_.Start(); + + // Results that require additional calculations + if (results_ != 0) { + timer_output_results_.Start(); + results_->CalcResults( clusters_ ); + timer_output_results_.Stop(); + } + + // Info + if (!suppressInfo_) { + CpptrajFile outfile; + if (outfile.OpenWrite( clusterinfo_ )) return 1; + timer_output_info_.Start(); + Output::PrintClustersToFile(outfile, clusters_, *algorithm_, metrics_, + frameSieve_.SieveValue(), frameSieve_.FramesToCluster()); + timer_output_info_.Stop(); + outfile.CloseFile(); + } + + // Silhouette + if (!sil_file_.empty()) { + if (frameSieve_.SieveValue() != 1 && !includeSieveInCalc_) + mprintf("Warning: Silhouettes do not include sieved frames.\n"); + clusters_.CalcSilhouette(metrics_, frameSieve_.SievedOut(), includeSieveInCalc_); + CpptrajFile Ffile, Cfile; + if (Ffile.OpenWrite(sil_file_ + ".frame.dat")) return 1; + Output::PrintSilhouetteFrames(Ffile, clusters_); + Ffile.CloseFile(); + if (Cfile.OpenWrite(sil_file_ + ".cluster.dat")) return 1; + Output::PrintSilhouettes(Cfile, clusters_); + Cfile.CloseFile(); + } + + // Print a summary of clusters + if (!summaryfile_.empty()) { + timer_output_summary_.Start(); + CpptrajFile outfile; + if (outfile.OpenWrite(summaryfile_)) { + mprinterr("Error: Could not set up cluster summary file.\n"); + return 1; + } + Output::Summary(outfile, clusters_, *algorithm_, metrics_, includeSieveInCalc_, + includeSieveCdist_, frameSieve_.SievedOut()); + timer_output_summary_.Stop(); + } + + // Summary by parts + if (!splitfile_.empty()) { + CpptrajFile outfile; + if (outfile.OpenWrite(splitfile_)) { + mprinterr("Error: Could not set up summary split file.\n"); + return 1; + } + BestReps findBestReps; + // TODO support > 1 best rep? + if (findBestReps.InitBestReps(bestRep_, 1, verbose_)) { + mprinterr("Error: Init of best reps calc for summary by parts failed.\n"); + return 1; + } + // TODO just pass in metrics_ + Output::Summary_Part(outfile, metrics_.Ntotal(), splitFrames_, clusters_, + findBestReps, metrics_, frameSieve_.SievedOut()); + } + + // Cluster number vs time + if (cnumvtime_ != 0) { + int err = 0; + if (grace_color_) + err = clusters_.CreateCnumVsTime(*((DataSet_integer*)cnumvtime_), metrics_.Ntotal(), 1, 15); + else + err = clusters_.CreateCnumVsTime(*((DataSet_integer*)cnumvtime_), metrics_.Ntotal(), 0, -1); + if (err != 0) { + mprinterr("Error: Creation of cluster num vs time data set failed.\n"); + return 1; + } + } + + // Draw cluster Graph + if (drawGraph_ != NO_DRAWGRAPH) { + DrawGraph( frameSieve_.FramesToCluster(), metrics_, drawGraph_, cnumvtime_, draw_tol_, draw_maxit_, debug_ ); + } + + // # unique clusters vs time + if (clustersVtime_ != 0) { + if (clusters_.NclustersObserved(*((DataSet_integer*)clustersVtime_), metrics_.Ntotal(), + windowSize_)) + { + mprinterr("Error: Creation of # unique clusters vs time data set failed.\n"); + return 1; + } + } + + // Cluster population vs time + if (cpopvtimefile_ != 0) { + MetaData md( dsname_, "Pop" ); + DataSet::SizeArray setsize(1, metrics_.Ntotal()); + for (List::cluster_iterator node = clusters_.begin(); + node != clusters_.end(); ++node) + { + md.SetIdx( node->Num() ); + DataSet_float* ds = (DataSet_float*)DSL.AddSet( DataSet::FLOAT, md ); + if (ds == 0) { + mprinterr("Error: Could not allocate cluster pop vs time DataSet\n"); + return 1; + } + ds->Allocate( setsize ); + if (cpopvtimefile_ != 0) cpopvtimefile_->AddDataSet( ds ); + node->CalcCpopVsTime( *ds, metrics_.Ntotal(), norm_pop_ ); + } + } + + // Cluster lifetime sets + if (calc_lifetimes_) { + MetaData md( dsname_, "Lifetime" ); + DataSet::SizeArray setsize(1, metrics_.Ntotal()); + for (List::cluster_iterator node = clusters_.begin(); + node != clusters_.end(); ++node) + { + md.SetIdx( node->Num() ); + DataSet_integer* ds = (DataSet_integer*)DSL.AddSet( DataSet::INTEGER, md ); + if (ds == 0) { + mprinterr("Error: Could not allocate cluster lifetime DataSet\n"); + return 1; + } + ds->Allocate( setsize ); + node->CreateLifetimeSet( *ds, metrics_.Ntotal() ); + } + } + + // Any other results + if (results_ != 0) { + timer_output_results_.Start(); + results_->DoOutput( clusters_ ); + timer_output_results_.Stop(); + } + + timer_output_.Stop(); + return 0; +} + +void Cpptraj::Cluster::Control::Timing(double ttotal) const { + mprintf("\tCluster timing data:\n"); + // Run Timing data + timer_setup_.WriteTiming( 2, "Cluster Init. :", timer_run_.Total()); + timer_pairwise_.WriteTiming( 2, "Pairwise Calc. :", timer_run_.Total()); + timer_cluster_.WriteTiming( 2, "Clustering :", timer_run_.Total()); + algorithm_->Timing( timer_cluster_.Total() ); + timer_post_.WriteTiming( 2, "Cluster Post. :", timer_run_.Total()); + timer_post_renumber_.WriteTiming( 3, "Cluster renumbering/sieve restore :", timer_post_.Total()); + timer_post_bestrep_.WriteTiming( 3, "Find best rep. :", timer_post_.Total()); + timer_run_.WriteTiming( 1, "Run Total :", ttotal); + // Output Timing data + timer_output_info_.WriteTiming( 2, "Info calc :", timer_output_.Total()); + timer_output_summary_.WriteTiming(2, "Summary calc :", timer_output_.Total()); + timer_output_results_.WriteTiming(2, "Results Output :", timer_output_.Total()); + timer_output_.WriteTiming(1, "Output Total :", ttotal); +} diff --git a/src/Cluster/Control.h b/src/Cluster/Control.h new file mode 100644 index 0000000000..4c9c9ad8c2 --- /dev/null +++ b/src/Cluster/Control.h @@ -0,0 +1,130 @@ +#ifndef INC_CLUSTER_CONTROL_H +#define INC_CLUSTER_CONTROL_H +#include "Algorithm.h" // Algorithm::AType +#include "BestReps.h" // BestReps::RepMethodType +#include "DrawGraph.h" // GraphType +#include "List.h" +#include "MetricArray.h" +#include "Node.h" // Node::CnormType +#include "Sieve.h" +#include "../Timer.h" +class DataSet_Coords; +class DataSet_PairwiseCache; +class DataFile; +class DataFileList; +class DataSetList; +namespace Cpptraj { +namespace Cluster { +class Algorithm; +class Results; +/// Hold clusters, algorithm, and pairwise matrix. +class Control { + public: + Control(); + ~Control(); + + /// Set debug level + void SetDebug(int d) { debug_ = d; } + + /// For determining how any sieved frames should be restored. + enum SieveRestoreType { NO_RESTORE = 0, CLOSEST_CENTROID, EPSILON_CENTROID, EPSILON_FRAME }; + /// For determining how frames to cluster will be determined. + enum FrameSelectType { UNSPECIFIED = 0, FROM_CACHE }; + + /// Setup clustering + int SetupClustering(DataSetList const&, DataSet*, ArgList&, DataSetList&, DataFileList&, int); + /// Provide information on how clustering calculation is currently set up. + void Info() const; + /// Perform clustering. + int Run(); + /// Do any clustering output. TODO make const? + int Output(DataSetList&); + /// Print timing data + void Timing(double) const; + /// Print help text to STDOUT + static void Help(); + private: + // Help keywords + static const char* AlgorithmArgs_; + static const char* CoordsDataSetArgs_; + static const char* SieveArgs1_; + static const char* SieveArgs2_; + static const char* BestRepArgs_; + static const char* OutputArgs1_; + static const char* OutputArgs2_; + static const char* OutputArgs3_; + static const char* OutputArgs4_; + static const char* GraphArgs_; + + /// \return Algorithm of given type + static Algorithm* AllocateAlgorithm(Algorithm::AType); + /// Allocate algorithm from keywords + int AllocateAlgorithm(ArgList&); + /// Initialize clusters from Info file + int ReadInfo(std::string const&); + /// Initialize clusters from cluster number vs time DataSet + int InitClustersFromSet(DataSet*); + + List clusters_; ///< Hold cluster results. + Sieve frameSieve_; ///< Hold frames to cluster, frames to "sieve" out. + MetricArray metrics_; ///< Hold the distance metrics and any cached distances. + Algorithm* algorithm_; ///< Hold the clustering algorithm. + Results* results_; ///< Hold output routines specific to data being clustered. + std::string dsname_; ///< Name for output data sets. + int verbose_; + + FrameSelectType frameSelect_; ///< How frames to cluster should be determined. + int sieve_; ///< Sieve value + int sieveSeed_; ///< Seed if doing random sieve + SieveRestoreType sieveRestore_; ///< Specify if/how sieved frames should be restored. + double restoreEpsilon_; ///< Cutoff to use if restoring by epsilon to centroids. + bool includeSieveInCalc_; ///< If true include sieved frames in later calculations. + bool includeSieveCdist_; ///< If true include sieved frames in cluster distance calc. + + BestReps::RepMethodType bestRep_; ///< How to determine best rep frames. + int nRepsToSave_; ///< How many rep frames to save. + + bool suppressInfo_; ///< If true do not write cluster info + std::string clusterinfo_; ///< Cluster info file name. + std::string summaryfile_; ///< Cluster summary file name. + std::string sil_file_; ///< File prefix for writing silhouette data + + DataSet* cnumvtime_; ///< Cluster number vs time data set. + bool grace_color_; ///< If true change cluster number to grace color + + DataSet* clustersVtime_; ///< Number of unique clusters vs time + int windowSize_; ///< Window size for determining number unique clusters v time + + DataFile* cpopvtimefile_; ///< Cluster population vs time file. + Node::CnormType norm_pop_; ///< Cluster pop vs time normalization type + + bool calc_lifetimes_; ///< If true create cluster lifetime data sets + + std::string splitfile_; ///< Output file for splitting cluster results + Cframes splitFrames_; ///< Frames at which to split + // TODO make class vars in DrawGraph.cpp + GraphType drawGraph_; ///< Indicate whether a cluster graph should be drawn + double draw_tol_; ///< Graph draw tolerance for min + int draw_maxit_; ///< Graph draw max iterations for min + + int debug_; ///< Cluster debug level + + CpptrajFile* metricContribFile_; ///< If not null, determine how much each metric contributes to total distance + + // Timers + Timer timer_setup_; ///< Run - metric, frames to cluster setup + Timer timer_pairwise_; ///< Run - pairwise caching + Timer timer_cluster_; ///< Run - clustering + Timer timer_post_; ///< Run - post-clustering calcs (rep frames etc) + Timer timer_post_renumber_; ///< Run Post - cluster sort/renumber + Timer timer_post_bestrep_; ///< Run Post - best rep frame calc + Timer timer_run_; ///< Total Run time + Timer timer_output_info_; ///< Output - info file write + Timer timer_output_summary_; ///< Output - summary write + Timer timer_output_results_; ///< Output - results (e.g. coords writes). + Timer timer_output_; ///< Total output time +}; + +} /** END namespace Cluster. */ +} /** END namespace Cpptraj. */ +#endif diff --git a/src/Cluster/DrawGraph.cpp b/src/Cluster/DrawGraph.cpp new file mode 100644 index 0000000000..2bd16d2c1a --- /dev/null +++ b/src/Cluster/DrawGraph.cpp @@ -0,0 +1,162 @@ +#include "DrawGraph.h" +#include "Cframes.h" +#include "MetricArray.h" +#include "../Constants.h" +#include "../CpptrajStdio.h" +#include "../DataSet_1D.h" +#include "../PDBfile.h" +#include "../Vec3.h" +#include +#include + +void Cpptraj::Cluster::DrawGraph(Cframes const& framesToCluster, MetricArray& pmatrix, + GraphType graphTypeIn, DataSet* cnumvtime, + double min_tol, int max_iteration, int debug) +{ + bool use_z; + if (graphTypeIn == NO_DRAWGRAPH) + return; + else if (graphTypeIn == THREED) + use_z = true; + else + use_z = false; + if (use_z) + mprintf("\tCreating PDB of graph points based on pairwise distances. B-factor = cluster #.\n"); + else + mprintf("\tAttempting to draw graph based on pairwise distances.\n"); + unsigned int nframes = framesToCluster.size(); + std::vector Xarray; // Coords + std::vector Farray; // Forces + Xarray.reserve( nframes ); + Farray.assign( nframes, Vec3(0.0) ); + // Initialize coordinates. X and Y only. + double zcoord = 0.0; + double theta_deg = 0.0; + double delta = 360.0 / (double)nframes; + for (unsigned int n = 0; n != nframes; n++, theta_deg += delta) { + double theta_rad = Constants::DEGRAD * theta_deg; + if (use_z) + zcoord = cos(theta_rad / 2.0); + Xarray.push_back( Vec3(cos(theta_rad), sin(theta_rad), zcoord) ); + } + // Write out initial graph + if (debug > 0 && !use_z) { + CpptrajFile graph0; + if (graph0.OpenWrite("InitialGraph.dat")) return; + for (std::vector::const_iterator XV = Xarray.begin(); + XV != Xarray.end(); ++XV) + graph0.Printf("%g %g %li\n", (*XV)[0], (*XV)[1], XV - Xarray.begin() + 1); + graph0.CloseFile(); + } + // Degrees of freedom. If Z ever initialized needs to be 3N + double deg_of_freedom = 2.0 * (double)nframes; + if (use_z) deg_of_freedom += (double)nframes; + double fnq = sqrt( deg_of_freedom ); + // Main loop for steepest descent + const double Rk = 1.0; + const double dxstm = 1.0E-5; + const double crits = 1.0E-6; + double rms = 1.0; + double dxst = 0.1; + double last_e = 0.0; + int iteration = 0; + mprintf(" \t%8s %12s %12s\n", " ", "ENE", "RMS"); + while (rms > min_tol && iteration < max_iteration) { + double e_total = 0.0; + //unsigned int idx = 0; // Index into FrameDistances + for (unsigned int f1 = 0; f1 != nframes; f1++) + { + for (unsigned int f2 = f1 + 1; f2 != nframes; f2++) + { + //double Req = FrameDistances().GetCdist(f1, f2); + Vec3 V1_2 = Xarray[f1] - Xarray[f2]; + double r2 = V1_2.Magnitude2(); + double s = sqrt(r2); + double r = 2.0 / s; + double db = s - pmatrix.Frame_Distance(framesToCluster[f1], framesToCluster[f2]);//FrameDistances().GetElement(idx++); + double df = Rk * db; + double e = df * db; + e_total += e; + df *= r; + // Apply force + V1_2 *= df; + Farray[f1] -= V1_2; + Farray[f2] += V1_2; + } + } + // Calculate the magnitude of the force vector. + double sum = 0.0; + for (std::vector::const_iterator FV = Farray.begin(); FV != Farray.end(); ++FV) + sum += FV->Magnitude2(); + rms = sqrt( sum ) / fnq; + // Adjust search step size + if (dxst < crits) dxst = dxstm; + dxst = dxst / 2.0; + if (e_total < last_e) dxst = dxst * 2.4; + double dxsth = dxst / sqrt( sum ); + last_e = e_total; + // Update positions and reset force array. + std::vector::iterator FV = Farray.begin(); + for (std::vector::iterator XV = Xarray.begin(); + XV != Xarray.end(); ++XV, ++FV) + { + *XV += (*FV * dxsth); + *FV = 0.0; + } + // Write out current E. + mprintf("Iteration:\t%8i %12.4E %12.4E\n", iteration, e_total, rms); + iteration++; + } + // RMS error + //unsigned int idx = 0; // Index into FrameDistances + double sumdiff2 = 0.0; + for (unsigned int f1 = 0; f1 != nframes; f1++) + { + for (unsigned int f2 = f1 + 1; f2 != nframes; f2++) + { + Vec3 V1_2 = Xarray[f1] - Xarray[f2]; + double r1_2 = sqrt( V1_2.Magnitude2() ); + double Req = pmatrix.Frame_Distance(framesToCluster[f1], framesToCluster[f2]);//FrameDistances().GetElement(idx); + double diff = r1_2 - Req; + sumdiff2 += (diff * diff); + if (debug > 0) + mprintf("\t\t%u to %u: D= %g Eq= %g Delta= %g\n", + f1+1, f2+1, r1_2, Req, fabs(diff)); + //++idx; + } + } + unsigned int Nelements = nframes * (nframes-1)/2; + double rms_err = sqrt( sumdiff2 / (double)Nelements ); + mprintf("\tRMS error of final graph positions: %g\n", rms_err); + // Write out final graph with cluster numbers. + std::vector Nums; + Nums.reserve( nframes ); + if (cnumvtime != 0) { + //ClusterSieve::SievedFrames const& sievedFrames = FrameDistances().FramesToCluster(); + DataSet_1D const& CVT = static_cast( *cnumvtime ); + for (unsigned int n = 0; n != nframes; n++) + Nums.push_back( (int)CVT.Dval(framesToCluster[n]) ); + } else + for (int n = 1; n <= (int)nframes; n++) + Nums.push_back( n ); + if (!use_z) { + CpptrajFile graph; + if (graph.OpenWrite("DrawGraph.dat")) return; + for (std::vector::const_iterator XV = Xarray.begin(); + XV != Xarray.end(); ++XV) + graph.Printf("%g %g %i \"%li\"\n", (*XV)[0], (*XV)[1], + Nums[XV - Xarray.begin()], XV - Xarray.begin() + 1); + graph.CloseFile(); + } else { + // Write out PDB with B-factors + PDBfile pdbout; + if (pdbout.OpenWrite("DrawGraph.pdb")) return; + pdbout.WriteTITLE("Cluster points."); + for (std::vector::const_iterator XV = Xarray.begin(); + XV != Xarray.end(); ++XV) + pdbout.WriteCoord(PDBfile::HETATM, XV - Xarray.begin() + 1, "HE", "HE", + XV - Xarray.begin() + 1, (*XV)[0], (*XV)[1], (*XV)[2], + 1.0, Nums[XV - Xarray.begin()], "HE", 0); + pdbout.CloseFile(); + } +} diff --git a/src/Cluster/DrawGraph.h b/src/Cluster/DrawGraph.h new file mode 100644 index 0000000000..914c406c17 --- /dev/null +++ b/src/Cluster/DrawGraph.h @@ -0,0 +1,15 @@ +#ifndef INC_CLUSTER_DRAWGRAPH_H +#define INC_CLUSTER_DRAWGRAPH_H +class DataSet; +namespace Cpptraj { +namespace Cluster { +class Cframes; +class MetricArray; + +enum GraphType { NO_DRAWGRAPH = 0, TWOD, THREED }; + +void DrawGraph(Cframes const&, MetricArray&, GraphType, DataSet*, double, int, int); + +} +} +#endif diff --git a/src/ClusterMatrix.cpp b/src/Cluster/DynamicMatrix.cpp similarity index 79% rename from src/ClusterMatrix.cpp rename to src/Cluster/DynamicMatrix.cpp index 295b7f4e9d..49245ca751 100644 --- a/src/ClusterMatrix.cpp +++ b/src/Cluster/DynamicMatrix.cpp @@ -1,20 +1,21 @@ -#include // FLT_MAX -#include "ClusterMatrix.h" -#include "CpptrajStdio.h" // PrintElements +#include // float max #ifdef _OPENMP -# include +#include #endif +#include "DynamicMatrix.h" +#include "../CpptrajStdio.h" -// ClusterMatrix::FindMin() +// DynamicMatrix::FindMin() /** Find the minimum not being ignored; set corresponding row and column. */ #ifdef _OPENMP -double ClusterMatrix::FindMin(int& iOut, int& jOut) { +double Cpptraj::Cluster::DynamicMatrix::FindMin(int& iOut, int& jOut) { int row, mythread; int nrows = (int)Mat_.Nrows(); # pragma omp parallel private(row, mythread) { mythread = omp_get_thread_num(); - minVal_[mythread] = FLT_MAX; + + minVal_[mythread] = std::numeric_limits::max(); # pragma omp for schedule(dynamic) for (row = 0; row < nrows; row++) { if (!ignore_[row]) { @@ -45,8 +46,8 @@ double ClusterMatrix::FindMin(int& iOut, int& jOut) { return (double)min; } #else -double ClusterMatrix::FindMin(int& iOut, int& jOut) const { - float min = FLT_MAX; +double Cpptraj::Cluster::DynamicMatrix::FindMin(int& iOut, int& jOut) const { + float min = std::numeric_limits::max(); for (unsigned int row = 0; row != Mat_.Nrows(); row++) { if (!ignore_[row]) { unsigned int col = row + 1; @@ -64,7 +65,7 @@ double ClusterMatrix::FindMin(int& iOut, int& jOut) const { } #endif -void ClusterMatrix::PrintElements() const { +void Cpptraj::Cluster::DynamicMatrix::PrintElements() const { unsigned int iVal = 0; unsigned int jVal = 1; for (size_t idx = 0UL; idx < Mat_.size(); ++idx) { @@ -79,8 +80,8 @@ void ClusterMatrix::PrintElements() const { } } -// ClusterMatrix::SetupMatrix() -int ClusterMatrix::SetupMatrix(size_t sizeIn) { +// DynamicMatrix::SetupMatrix() +int Cpptraj::Cluster::DynamicMatrix::SetupMatrix(size_t sizeIn) { if (Mat_.resize( 0L, sizeIn )) return 1; ignore_.assign( sizeIn, false ); # ifdef _OPENMP diff --git a/src/ClusterMatrix.h b/src/Cluster/DynamicMatrix.h similarity index 84% rename from src/ClusterMatrix.h rename to src/Cluster/DynamicMatrix.h index cf5b3f2f2a..bcfee8be0c 100644 --- a/src/ClusterMatrix.h +++ b/src/Cluster/DynamicMatrix.h @@ -1,11 +1,14 @@ -#ifndef INC_CLUSTERMATRIX_H -#define INC_CLUSTERMATRIX_H +#ifndef INC_CLUSTER_DYNAMICMATRIX_H +#define INC_CLUSTER_DYNAMICMATRIX_H #include -#include "Matrix.h" -/// Used to hold distances between clusters. -class ClusterMatrix { +#include "../Matrix.h" +namespace Cpptraj { +namespace Cluster { + +/// Hold between-cluster distances and whether cluster is still present. +class DynamicMatrix { public: - ClusterMatrix() {} + DynamicMatrix() {} /// Indicate given row/col should be ignored. void Ignore(int row) { ignore_[row] = true; } /// \return true if given row/col has been ignored. @@ -37,4 +40,7 @@ class ClusterMatrix { std::vector minVal_; # endif }; + +} +} #endif diff --git a/src/Cluster/List.cpp b/src/Cluster/List.cpp new file mode 100644 index 0000000000..7bc9e745a6 --- /dev/null +++ b/src/Cluster/List.cpp @@ -0,0 +1,511 @@ +#include // std::max +#include // double max +#include "List.h" +#include "MetricArray.h" +#include "Node.h" +#include "../CpptrajStdio.h" +#include "../DataSet_integer.h" +#include "../ProgressBar.h" +#include "../Constants.h" // SMALL TODO use limits? +#ifdef _OPENMP +# include +#endif + +void Cpptraj::Cluster::List::PrintClusters() const { + //mprintf("CLUSTER: %u clusters, %u frames.\n", clusters_.size(), + // FrameDistances().OriginalNframes() ); + mprintf("CLUSTER: %zu clusters.\n", clusters_.size()); + for (cluster_iterator C = begincluster(); C != endcluster(); C++) { + mprintf("\t%8i : ",C->Num()); + for (Node::frame_iterator fnum = C->beginframe(); + fnum != C->endframe(); ++fnum) + mprintf("%i,",(*fnum)+1); + mprintf("\n"); + } +} + +/** Create cluster number vs time data set. + * \param ds The output integer DataSet + * \param maxFrames The maximum number of frames. + * \param offset If specified, add offset to cluster numbers. + * \param maxCluster If specified, number clusters beyond maxCluster equal to maxCluster + */ +int Cpptraj::Cluster::List::CreateCnumVsTime(DataSet_integer& cnum_temp, unsigned int maxFrames, + int offset, int maxCluster) +const +{ + // Make all clusters start at -1. This way cluster algorithms that + // have noise points (i.e. no cluster assigned) will be distinguished. + cnum_temp.Assign( maxFrames, NOISE + offset ); + + if (offset == 0 && maxCluster < 0) { + for (cluster_iterator C = begincluster(); C != endcluster(); C++) + { + //mprinterr("Cluster %i:\n",CList->CurrentNum()); + int cnum = C->Num(); + // Loop over all frames in the cluster + for (Node::frame_iterator frame = C->beginframe(); frame != C->endframe(); frame++) + { + //mprinterr("%i,",*frame); + cnum_temp.SetElement( *frame, cnum ); + } + //mprinterr("\n"); + //break; + } + } else { + for (cluster_iterator C = begincluster(); C != endcluster(); C++) + { + int cnum = C->Num() + offset; + if (cnum > maxCluster) + cnum = maxCluster; + // Loop over all frames in the cluster + for (Node::frame_iterator frame = C->beginframe(); frame != C->endframe(); frame++) + cnum_temp.SetElement( *frame , cnum ); + } + } + return 0; +} + +/** Determine how many different clusters are observed within a given time + * window. + */ +int Cpptraj::Cluster::List::NclustersObserved(DataSet_integer& clustersVtime, + unsigned int maxFrames, + int windowSize) +const +{ + if (windowSize < 1) { + mprinterr("Error: Invalid window size for number clusters observed vs time.\n"); + return 1; + } + // Determine number of windows + int nwindows = (int)maxFrames / windowSize; + if (((int)maxFrames % windowSize) != 0) nwindows++; + if (debug_ > 0) + mprintf("DEBUG: %u frames, %i windows, window size %i.\n", maxFrames, nwindows, windowSize); + + // Create a bool array for each window that will record if cluster is present + // during that window. + typedef std::vector Barray; + typedef std::vector Warray; + Warray Windows; + Windows.reserve( nwindows ); + for (int w = 0; w != nwindows; w++) + Windows.push_back( Barray(Nclusters(), false) ); + + // Loop over clusters + for (cluster_iterator C = begincluster(); C != endcluster(); C++) + { + // Loop over cluster frames + for (Node::frame_iterator frame = C->beginframe(); frame != C->endframe(); frame++) + { + int wndw = *frame / windowSize; + Windows[wndw][C->Num()] = true; + } + } + + // Count number of unique clusters in each window + clustersVtime.Allocate( DataSet::SizeArray(1, nwindows) ); + int wndw = 0; + for (Warray::const_iterator window = Windows.begin(); window != Windows.end(); ++window, ++wndw) + { + int nunique = 0; + for (Barray::const_iterator cpresent = window->begin(); cpresent != window->end(); ++cpresent) + if (*cpresent) ++nunique; + clustersVtime.Add(wndw, &nunique); + } + + clustersVtime.SetDim(Dimension::X, Dimension(windowSize, windowSize, "Frame")); + return 0; +} + +/** Sort clusters by population and renumber. */ +int Cpptraj::Cluster::List::Sort() { + clusters_.sort(); + int newNum = 0; + for (cluster_it it = clusters_.begin(); it != clusters_.end(); ++it) + it->SetNum( newNum++ ); + return 0; +} + +/** Update centroids. */ +void Cpptraj::Cluster::List::UpdateCentroids( MetricArray& metric ) { + for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) { + node->SortFrameList(); + node->CalculateCentroid( metric ); + } +} + +/** Remove clusters with no population. */ +void Cpptraj::Cluster::List::RemoveEmptyClusters() { + cluster_it cnode = clusters_.begin(); + while (cnode != clusters_.end()) { + if (cnode->Nframes() == 0) + cnode = clusters_.erase( cnode ); + else + ++cnode; + } +} + +/** Clear everything. */ +void Cpptraj::Cluster::List::Clear() { + clusters_.clear(); + noise_.clear(); +} + +// ----------------------------------------------------------------------------- +void Cpptraj::Cluster::List::AddFramesByCentroid(Cframes const& framesIn, MetricArray& metricIn) +{ + // NOTE: All cluster centroids must be up to date. + int idx; + int nframes = (int)framesIn.size(); + double mindist, dist; + cluster_it minNode, Cnode; + ParallelProgress progress( nframes ); + // For OMP, every other thread will need its own Cdist. + MetricArray* MyCdist = &metricIn; +# ifdef _OPENMP + // For OMP need a temp. array to hold which frame goes to which cluster to avoid clashes + std::vector idxToCluster( nframes, clusters_.end() ); +# pragma omp parallel private(MyCdist, idx, dist, mindist, minNode, Cnode) firstprivate(progress) + { + int mythread = omp_get_thread_num(); + progress.SetThread( mythread ); + if (mythread == 0) { + mprintf("\tParallelizing sieve restore calc with %i threads\n", omp_get_num_threads()); + MyCdist = &metricIn; + } else + MyCdist = new MetricArray(metricIn); +# pragma omp for +# endif + for (idx = 0; idx < nframes; ++idx) { + progress.Update( idx ); + int frame = framesIn[idx]; + // Which clusters centroid is closest to this frame? + mindist = std::numeric_limits::max(); + minNode = clusters_.end(); + for (Cnode = clusters_.begin(); Cnode != clusters_.end(); ++Cnode) { + dist = MyCdist->FrameCentroidDist(frame, Cnode->Cent()); + if (dist < mindist) { + mindist = dist; + minNode = Cnode; + } + } + // Add sieved frame to the closest cluster. +# ifdef _OPENMP + idxToCluster[idx] = minNode; +# else + minNode->AddFrameToCluster( frame ); +# endif + } // END loop over frames +# ifdef _OPENMP + if (mythread > 0) + delete MyCdist; + } // END pragma omp parallel + // Now actually add sieved frames to their appropriate clusters + for (idx = 0; idx < nframes; idx++) + if (idxToCluster[idx] != clusters_.end()) + idxToCluster[idx]->AddFrameToCluster( framesIn[idx] ); +# endif + progress.Finish(); +} + +/** Add frames to clusters that are within epsilon of a cluster centroid (if + * sieveToCentroid) or epsilon of any frame in a cluster otherwise. + */ +void Cpptraj::Cluster::List::AddFramesByCentroid(Cframes const& framesIn, MetricArray& metricIn, + bool sieveToCentroid, double epsilon) +{ + // NOTE: All cluster centroids must be up to date! + if (sieveToCentroid) + mprintf("\tRestoring sieved frames if within %.3f of cluster centroid.\n", epsilon); + else + mprintf("\tRestoring sieved frames if within %.3f of frame in nearest cluster.\n", + epsilon); + // Vars allocated here in case of OpenMP + int n_sieved_noise = 0; + int Nsieved = 0; + int idx; + int nframes = (int)framesIn.size(); + ParallelProgress progress( nframes ); + // Need a temporary array to hold which frame belongs to which cluster. + // Otherwise we could be comparoing sieved frames to other sieved frames. + std::vector idxToCluster( nframes, clusters_.end() ); + // For OMP, every other thread will need its own Cdist. + MetricArray* MyCdist = &metricIn; +# ifdef _OPENMP +# pragma omp parallel private(MyCdist, idx) firstprivate(progress) reduction(+ : Nsieved, n_sieved_noise) + { + int mythread = omp_get_thread_num(); + progress.SetThread( mythread ); + if (mythread == 0) { + mprintf("\tParallelizing calculation with %i threads\n", omp_get_num_threads()); + MyCdist = &metricIn; + } else + MyCdist = new MetricArray(metricIn); +# pragma omp for +# endif + for (idx = 0; idx < nframes; ++idx) { + progress.Update( idx ); + int frame = framesIn[idx]; + // Which clusters centroid is closest to this frame? + double mindist = std::numeric_limits::max(); + cluster_it minNode = clusters_.end(); + for (cluster_it Cnode = clusters_.begin(); Cnode != clusters_.end(); ++Cnode) { + double dist = MyCdist->FrameCentroidDist(frame, Cnode->Cent()); + if (dist < mindist) { + mindist = dist; + minNode = Cnode; + } + } + bool goodFrame = false; + if ( mindist < epsilon ) + // Frame is already within epsilon, accept. + goodFrame = true; + else if ( !sieveToCentroid ) { + // Check if any frames in the cluster are closer than epsilon to sieved frame. + for (int cidx=0; cidx < minNode->Nframes(); cidx++) + { //TODO just use PairwiseMatrix::Frame_Distance here? + if ( MyCdist->Frame_Distance(frame, minNode->ClusterFrame(cidx)) < epsilon ) + { + goodFrame = true; + break; + } + } + } + // Add sieved frame to the closest cluster if closest distance is + // less than epsilon. + ++Nsieved; + if ( goodFrame ) + idxToCluster[idx] = minNode; + else + n_sieved_noise++; + } // END loop over frames +# ifdef _OPENMP + if (mythread > 0) + delete MyCdist; + } // END pragma omp parallel +# endif + progress.Finish(); + // Now actually add sieved frames to their appropriate clusters + for (idx = 0; idx < nframes; idx++) + if (idxToCluster[idx] != clusters_.end()) + idxToCluster[idx]->AddFrameToCluster( framesIn[idx] ); + mprintf("\t%i of %i sieved frames were discarded as noise.\n", + n_sieved_noise, Nsieved); +} + +// ----------------------------------------------------------------------------- +/** The Davies-Bouldin Index (DBI) measures the average similarity between each + * cluster and its most similar one; the smaller the DBI, the better. The DBI + * is defined as the average, for all clusters X, of fred, where fred(X) = max, + * across other clusters Y, of (Cx + Cy)/dXY. Here Cx is the average distance + * from points in X to the centroid, similarly Cy, and dXY is the distance + * between cluster centroids. + * NOTE: To use this, cluster centroids should be fully up-to-date. + */ +double Cpptraj::Cluster::List::ComputeDBI(std::vector& averageDist, MetricArray& metricIn) +const +{ + averageDist.clear(); + averageDist.reserve( clusters_.size() ); + for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) { + // Calculate average distance to centroid for this cluster + averageDist.push_back( C1->CalcAvgToCentroid( metricIn ) ); + //if (outfile.IsOpen()) + // outfile.Printf("#Cluster %i has average-distance-to-centroid %f\n", + // C1->Num(), averageDist.back()); + } + double DBITotal = 0.0; + unsigned int nc1 = 0; + for (cluster_iterator c1 = begincluster(); c1 != endcluster(); ++c1, ++nc1) { + double MaxFred = 0; + unsigned int nc2 = 0; + for (cluster_iterator c2 = begincluster(); c2 != endcluster(); ++c2, ++nc2) { + if (c1 != c2) { + double Fred = averageDist[nc1] + averageDist[nc2]; + Fred /= metricIn.CentroidDist( c1->Cent(), c2->Cent() ); + if (Fred > MaxFred) + MaxFred = Fred; + } + } + DBITotal += MaxFred; + } + DBITotal /= (double)clusters_.size(); + //if (outfile.IsOpen()) outfile.Printf("#DBI: %f\n", DBITotal); + return DBITotal; +} + +/** The pseudo-F statistic is another measure of clustering goodness. It is + * intended to capture the 'tightness' of clusters, and is in essence a ratio + * of the mean sum of squares between groups to the mean sum of squares within + * group (Lattin et al., 2003: 291) High values are good. Generally, one + * selects a cluster-count that gives a peak in the pseudo-f statistic (or + * pSF, for short). + * Formula: A/B, where A = (T - P)/(G-1), and B = P / (n-G). Here n is the + * number of points, G is the number of clusters, T is the total distance from + * the all-data centroid, and P is the sum (for all clusters) of the distances + * from the cluster centroid. + * NOTE: To use this, cluster centroids should be fully up-to-date. + * NOTE: This calc differs slightly from PTRAJ in that real centroids are used + * instead of representative structures. + */ +double Cpptraj::Cluster::List::ComputePseudoF(double& SSRSST, MetricArray& metricIn) const +{ + // Calculation makes no sense with fewer than 2 clusters. + if (Nclusters() < 2) { + mprintf("Warning: Fewer than 2 clusters. Not calculating pseudo-F.\n"); + return 0.0; + } + + // Form a cluster with all points to get a centroid. Use only frames that + // are in clusters, i.e. ignore noise. Assumes all cluster centroids are + // up to date. + Node c_all; + for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) + { + for (Node::frame_iterator f1 = C1->beginframe(); f1 != C1->endframe(); ++f1) + c_all.AddFrameToCluster( *f1 ); + } + // Pseudo-F makes no sense if # clusters == # frames + if (Nclusters() == c_all.Nframes()) { + mprintf("Warning: Each frame is in a separate cluster. Not calculating pseudo-F.\n"); + return 0.0; + } + c_all.SortFrameList(); + c_all.CalculateCentroid( metricIn ); + + // Loop over all clusters + double gss = 0.0; // between-group sum of squares + double wss = 0.0; // within-group sum of squares + for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) + { + for (Node::frame_iterator f1 = C1->beginframe(); f1 != C1->endframe(); ++f1) + { + double dist = metricIn.FrameCentroidDist(*f1, c_all.Cent()); + gss += (dist * dist); + dist = metricIn.FrameCentroidDist(*f1, C1->Cent()); + wss += (dist * dist); + } + } + double d_nclusters = (double)Nclusters(); + double d_ntotal = (double)c_all.Nframes(); + double num = (gss - wss) / (d_nclusters - 1.0); + double den = wss / (d_ntotal - d_nclusters); + if (den < Constants::SMALL) + den = Constants::SMALL; + double pseudof = num / den; + if (debug_ > 0) + mprintf("Pseudo-f: Total distance to centroid is %.4f\n" + "Pseudo-f: Cluster distance to centroid is %.4f\n" + "Pseudo-f: Numerator %.4f over denominator %.4f gives %.4f\n", + gss, wss, num, den, pseudof); + //if (outfile.IsOpen()) { + // outfile.Printf("#pSF: %f\n", pseudof); + // This calculation taken directly from ptraj + SSRSST = pseudof*(d_nclusters-1)/(d_ntotal-d_nclusters+pseudof*(d_nclusters-1)); + // outfile.Printf("#SSR/SST: %f\n", SSRSST); + //} + + return pseudof; +} + +/** The cluster silhouette is a measure of how well each point fits within + * a cluster. Values of 1 indicate the point is very similar to other points + * in the cluster, i.e. it is well-clustered. Values of -1 indicate the point + * is dissimilar and may fit better in a neighboring cluster. Values of 0 + * indicate the point is on a border between two clusters. + */ +int Cpptraj::Cluster::List::CalcSilhouette(MetricArray& metrics, + Cframes const& sievedFrames, + bool includeSieved) +{ + for (cluster_it Ci = begin(); Ci != end(); ++Ci) + { + Node::SilPairArray& SiVals = Ci->FrameSilhouettes(); + SiVals.clear(); + SiVals.reserve( Ci->Nframes() ); + double avg_si = 0.0; + int ci_frames = 0; + for (Node::frame_iterator f1 = Ci->beginframe(); f1 != Ci->endframe(); ++f1) + { + if (includeSieved || !sievedFrames.HasFrame( *f1 )) { + // Calculate the average dissimilarity of this frame with all other + // points in this frames cluster. + double ai = 0.0; + int self_frames = 0; + if (includeSieved) { + for (Node::frame_iterator f2 = Ci->beginframe(); f2 != Ci->endframe(); ++f2) + { + if (f1 != f2) { + ai += metrics.Frame_Distance(*f1, *f2); + ++self_frames; + } + } + } else { + for (Node::frame_iterator f2 = Ci->beginframe(); f2 != Ci->endframe(); ++f2) + { + if (f1 != f2 && !sievedFrames.HasFrame(*f2)) { + ai += metrics.Frame_Distance(*f1, *f2); + ++self_frames; + } + } + } + if (self_frames > 0) + ai /= (double)self_frames; + //mprintf("\t\tFrame %i cluster %i ai = %g\n", *f1+1, Ci->Num(), ai); + // Determine lowest average dissimilarity of this frame with all + // other clusters. + double min_bi = std::numeric_limits::max(); + for (cluster_iterator Cj = begincluster(); Cj != endcluster(); ++Cj) + { + if (Ci != Cj) + { + double bi = 0.0; + // NOTE: ASSUMING NO EMPTY CLUSTERS + if (includeSieved) { + for (Node::frame_iterator f2 = Cj->beginframe(); f2 != Cj->endframe(); ++f2) + bi += metrics.Frame_Distance(*f1, *f2); + bi /= (double)Cj->Nframes(); + } else { + int cj_frames = 0; + for (Node::frame_iterator f2 = Cj->beginframe(); f2 != Cj->endframe(); ++f2) + { + if (!sievedFrames.HasFrame(*f2)) { + bi += metrics.Frame_Distance(*f1, *f2); + ++cj_frames; + } + } + bi /= (double)cj_frames; + } + //mprintf("\t\tFrame %i to cluster %i bi = %g\n", *f1 + 1, Cj->Num(), bi); + if (bi < min_bi) + min_bi = bi; + } + } + double max_ai_bi = std::max( ai, min_bi ); + if (max_ai_bi == 0.0) + mprinterr("Error: Divide by zero in silhouette calculation for frame %i\n", *f1 + 1); + else { + double si = (min_bi - ai) / max_ai_bi; + SiVals.push_back( Node::SilPair(*f1, si) ); + avg_si += si; + ++ci_frames; + } + } // END if frame should be calcd + } // END loop over cluster frames + //std::sort( SiVals.begin(), SiVals.end() ); + // DEBUG + if (debug_ > 1) { + mprintf("DEBUG: Cluster frame silhouette values for cluster %i\n", Ci->Num()); + for (Node::SilPairArray::const_iterator it = Ci->FrameSilhouettes().begin(); + it != Ci->FrameSilhouettes().end(); ++it) + mprintf("\t%8i %g\n", it->first+1, it->second); + } + if (ci_frames > 0) + avg_si /= (double)ci_frames; + //mprintf("DEBUG: Cluster silhouette: %8i %g\n", Ci->Num(), avg_si); + Ci->SetSilhouette( avg_si ); + } // END outer loop over clusters + return 0; +} diff --git a/src/Cluster/List.h b/src/Cluster/List.h new file mode 100644 index 0000000000..713d9fe976 --- /dev/null +++ b/src/Cluster/List.h @@ -0,0 +1,82 @@ +#ifndef INC_CLUSTER_LIST_H +#define INC_CLUSTER_LIST_H +#include +#include "Cframes.h" +class DataSet_integer; +namespace Cpptraj { +namespace Cluster { +class MetricArray; +class Node; +/// Hold all individual clusters. +/** Currently implemented as an STL list since sorting and erasing are more + * efficient. + */ +class List { + public: + List() {} + /// Set debug level + void SetDebug(int d) { debug_ = d; } + /// Iterator over clusters + typedef std::list::iterator cluster_it; + /// Iterator to beginning + cluster_it begin() { return clusters_.begin(); } + /// Iterator to end + cluster_it end() { return clusters_.end(); } + /// Const iterator over clusters + typedef std::list::const_iterator cluster_iterator; + /// Const iterator to beginning + const cluster_iterator begincluster() const { return clusters_.begin(); } + /// Const iterator to end + const cluster_iterator endcluster() const { return clusters_.end(); } + /// \return first cluster + Node const& front() const { return clusters_.front(); } + /// \return last cluster + Node const& back() const { return clusters_.back(); } + /// \return current number of clusters. + int Nclusters() const { return (int)clusters_.size(); } + /// \return true if no clusters + bool empty() const { return clusters_.empty(); } + /// \return Array containing noise points + Cframes const& Noise() const { return noise_; } + /// Print clusters to stdout + void PrintClusters() const; + /// Add new cluster + void AddCluster( Node const& n ) { clusters_.push_back( n ); } + /// Remove existing cluster via iterator + void RemoveCluster( cluster_it& it ) { clusters_.erase( it ); } + /// Remove clusters with no population + void RemoveEmptyClusters(); + /// Remove all clusters + void Clear(); + /// Generate cluster number vs time data set + int CreateCnumVsTime(DataSet_integer&, unsigned int, int, int) const; + /// Generate number unique clusters vs time data set + int NclustersObserved(DataSet_integer&, unsigned int, int) const; + /// Sort clusters by population and renumber. + int Sort(); + /// Add given frame as noise. + void AddNoise(int f) { noise_.push_back( f ); } + /// Update centroids TODO check if they need updating + void UpdateCentroids(MetricArray&); + /// Add given frames to clusters based on distance to centroid. TODO save original frames + void AddFramesByCentroid(Cframes const&, MetricArray&); + /// Add given frames to clusters based on distance to centroid and cutoff. + void AddFramesByCentroid(Cframes const&, MetricArray&, bool, double); + + /// Calculate the Davies-Bouldin index. + double ComputeDBI(std::vector&, MetricArray&) const; + /// Calculate pseudo-F + double ComputePseudoF(double&, MetricArray&) const; + /// Calculate cluster and cluster frame silhouettes TODO data sets + int CalcSilhouette(MetricArray&, Cframes const&, bool); + private: + typedef std::list Narray; + Narray clusters_; ///< Hold all clusters. + Cframes noise_; ///< Hold any frames classified as noise. + int debug_; +}; + +} /* END namespace Cluster */ +} /* END namespace Cpptraj */ + +#endif diff --git a/src/Cluster/Makefile b/src/Cluster/Makefile new file mode 100644 index 0000000000..933e2b0942 --- /dev/null +++ b/src/Cluster/Makefile @@ -0,0 +1,38 @@ +# Cluster code library Makefile +include ../../config.h + +include clusterfiles + +DEL_FILE = /bin/rm -f +AR = ar cqs +TARGET = libcpptraj_cluster.a + +# Objects +OBJECTS=$(CLUSTER_SOURCES:.cpp=.o) + +#CLUSTER_TARGET=Cluster/libcpptraj_cluster.a + +# Default target: library +all: $(TARGET) + +# Build library +$(TARGET): $(OBJECTS) + -$(DEL_FILE) $(TARGET) + $(AR) $(TARGET) $(OBJECTS) + +clean: + $(DEL_FILE) *.o $(TARGET) + +uninstall: clean + +# Dependency targets +../findDepend: + cd ../ && $(MAKE) findDepend + +depend: ../findDepend + ../findDepend $(CLUSTER_SOURCES) > clusterdepend + +#dependclean: +# $(DEL_FILE) FindDepend.o findDepend + +include clusterdepend diff --git a/src/Cluster/Metric.h b/src/Cluster/Metric.h new file mode 100644 index 0000000000..bfa561c35e --- /dev/null +++ b/src/Cluster/Metric.h @@ -0,0 +1,55 @@ +#ifndef INC_CLUSTER_METRIC_H +#define INC_CLUSTER_METRIC_H +#include +#include +namespace Cpptraj { +namespace Cluster { +class Centroid; +class Cframes; +/// Definition of a noise point. +const int NOISE = -1; +/// Definition of an unclassified point. +const int UNCLASSIFIED = -2; + +/// Abstract base class for calculating distance between points or determining centroid. +class Metric { + public: + enum Type { RMS=0, DME, SRMSD, SCALAR, TORSION, MATRIX2D, UNKNOWN_METRIC }; + enum CentOpType { ADDFRAME=0, SUBTRACTFRAME }; + + /// CONSTRUCTOR + Metric(Type t) { type_ = t; } + /// DESTRUCTOR + virtual ~Metric() {} + /// Set up the Metric prior to clustering. + virtual int Setup() = 0; + /// \return distance between given frames. + virtual double FrameDist(int, int) = 0; + /// \return distance between given centroids. + virtual double CentroidDist( Centroid*, Centroid* ) = 0; + /// \return distance between given frame and centroid. + virtual double FrameCentroidDist(int, Centroid* ) = 0; + /// Calculate centroid from given frames. + virtual void CalculateCentroid(Centroid*, Cframes const&) = 0; + /// \return new centroid from given frames. + virtual Centroid* NewCentroid(Cframes const&) = 0; + /// \return copy of this Metric + virtual Metric* Copy() = 0; + /// Update centroid by performing given operation between given frame and centroid. + virtual void FrameOpCentroid(int, Centroid*, double, CentOpType) = 0; + /// \return string containing description of the distance metric + virtual std::string Description() const = 0; + /// Print Metric info to stdout. + virtual void Info() const = 0; + /// \return total number of frames. + virtual unsigned int Ntotal() const = 0; + + /// \return Metric type + Type MetricType() const { return type_; } + private: + Type type_; +}; + +} // END namespace Cluster +} // END namepsace Cpptraj +#endif diff --git a/src/Cluster/MetricArray.cpp b/src/Cluster/MetricArray.cpp new file mode 100644 index 0000000000..9d0636a0ca --- /dev/null +++ b/src/Cluster/MetricArray.cpp @@ -0,0 +1,781 @@ +#include "MetricArray.h" +#include // std::min,max +#include //sqrt +// For filling the pairwise cache +#ifdef _OPENMP +#include +#endif +#include "CentroidArray.h" +#include "Metric.h" +#include "../ArgList.h" +#include "../CpptrajFile.h" +#include "../CpptrajStdio.h" +#include "../DataFile.h" +#include "../DataFileList.h" +#include "../DataSet_PairwiseCache.h" +#include "../DataSetList.h" +#include "../OnlineVarT.h" // for metric stats average +#include "../ProgressBar.h" +#include "../StringRoutines.h" +// Metric classes +#include "Metric_RMS.h" +#include "Metric_DME.h" +#include "Metric_Scalar.h" +#include "Metric_SRMSD.h" +#include "Metric_Torsion.h" + +/** CONSTRUCTOR */ +Cpptraj::Cluster::MetricArray::MetricArray() : + debug_(0), + type_(MANHATTAN), + ntotal_(0), + cache_(0), + cacheWasAllocated_(false), + pw_mismatch_fatal_(true) +{} + +/** DESTRUCTOR */ +Cpptraj::Cluster::MetricArray::~MetricArray() { + Clear(); +} + +/** COPY CONSTRUCTOR */ +Cpptraj::Cluster::MetricArray::MetricArray(MetricArray const& rhs) : + sets_(rhs.sets_), + weights_(rhs.weights_), + temp_(rhs.temp_), + debug_(rhs.debug_), + type_(rhs.type_), + ntotal_(rhs.ntotal_), + cache_(rhs.cache_), + cacheWasAllocated_(rhs.cacheWasAllocated_), + pw_mismatch_fatal_(rhs.pw_mismatch_fatal_) +{ + metrics_.reserve( rhs.metrics_.size() ); + for (std::vector::const_iterator it = rhs.metrics_.begin(); it != rhs.metrics_.end(); ++it) + metrics_.push_back( (*it)->Copy() ); +} + +/** ASSIGNMENT */ +Cpptraj::Cluster::MetricArray& + Cpptraj::Cluster::MetricArray::operator=(MetricArray const& rhs) +{ + if (this == &rhs) return *this; + metrics_.clear(); + metrics_.reserve( rhs.metrics_.size() ); + for (std::vector::const_iterator it = rhs.metrics_.begin(); it != rhs.metrics_.end(); ++it) + metrics_.push_back( (*it)->Copy() ); + sets_ = rhs.sets_; + weights_ = rhs.weights_; + temp_ = rhs.temp_; + debug_ = rhs.debug_; + type_ = rhs.type_; + ntotal_ = rhs.ntotal_; + cache_ = rhs.cache_; + cacheWasAllocated_ = rhs.cacheWasAllocated_; + pw_mismatch_fatal_ = rhs.pw_mismatch_fatal_; + return *this; +} + +/** Clear the metric array. */ +void Cpptraj::Cluster::MetricArray::Clear() { + for (std::vector::iterator it = metrics_.begin(); it != metrics_.end(); ++it) + delete *it; + sets_.clear(); + weights_.clear(); + temp_.clear(); + cache_ = 0; + cacheWasAllocated_ = false; + pw_mismatch_fatal_ = true; +} + +/** Pairwise args 1 */ +const char* Cpptraj::Cluster::MetricArray::PairwiseArgs1_ = + "[pairdist ] [pwrecalc]"; + +/** Pairwise args 2 */ +const char* Cpptraj::Cluster::MetricArray::PairwiseArgs2_ = + "[loadpairdist] [savepairdist] [pairwisecache {mem|disk|none}]"; + + +/** Set up pairwise cache from arguments. */ +int Cpptraj::Cluster::MetricArray::setupPairwiseCache(ArgList& analyzeArgs, + DataSetList& DSL, + DataFileList& DFL) +{ + if (metrics_.empty()) { + mprinterr("Internal Error: allocatePairwise(): No Metrics.\n"); + return 1; + } + cacheWasAllocated_ = false; + // The default pairwise cache file/dataset name + const char* DEFAULT_PAIRDIST_NAME_ = "CpptrajPairDist"; + // The default pairwise cache file type + DataFile::DataFormatType DEFAULT_PAIRDIST_TYPE_ = +# ifdef BINTRAJ + DataFile::CMATRIX_NETCDF; +# else + DataFile::CMATRIX_BINARY; +# endif + + // Determine if we are saving/loading pairwise distances + std::string pairdistname = analyzeArgs.GetStringKey("pairdist"); + DataFile::DataFormatType pairdisttype = DataFile::UNKNOWN_DATA; + bool load_pair = analyzeArgs.hasKey("loadpairdist"); + bool save_pair = analyzeArgs.hasKey("savepairdist"); + // Check if we need to set a default file name +/* std::string fname; + if (pairdistname.empty()) + fname = DEFAULT_PAIRDIST_NAME_; + else { + fname = pairdistname; + // To remain backwards compatible, assume we want to load if + // a pairdist name was specified. + if (!load_pair && !save_pair) { + mprintf("Warning: 'pairdist' specified but 'loadpairdist'/'savepairdist' not specified." + "Warning: Assuming 'loadpairdist'.\n"); + load_pair = true; + } + }*/ + + cache_ = 0; + if (load_pair || + (!save_pair && !pairdistname.empty())) + { + // If 'loadpairdist' specified or 'pairdist' specified and 'savepairdist' + // not specified, we either want to load from file or use an existing + // data set. + if (pairdistname.empty()) { + pairdistname = DEFAULT_PAIRDIST_NAME_; + pairdisttype = DEFAULT_PAIRDIST_TYPE_; + } + // First check if pairwise data exists + DataSetList selected = DSL.SelectGroupSets( pairdistname, DataSet::PWCACHE ); + if (!selected.empty()) { + if (selected.size() > 1) + mprintf("Warning: '%s' matches multiple sets; only using '%s'\n", + pairdistname.c_str(), selected[0]->legend()); + cache_ = (DataSet_PairwiseCache*)selected[0]; + mprintf("\tUsing existing pairwise set '%s'\n", cache_->legend()); + // Next check if file exists + } else if (File::Exists( pairdistname )) { + mprintf("\tLoading pairwise distances from file '%s'\n", pairdistname.c_str()); + DataFile dfIn; + // TODO set data set name with ArgList? + if (dfIn.ReadDataIn( pairdistname, ArgList(), DSL )) return 1; + DataSet* ds = DSL.GetDataSet( pairdistname ); + if (ds == 0) return 1; + if (ds->Group() != DataSet::PWCACHE) { + mprinterr("Internal Error: AllocatePairwise(): Set is not a pairwise cache.\n"); + return 1; + } + cache_ = (DataSet_PairwiseCache*)ds; + if (cache_ != 0 && save_pair) { + mprintf("Warning: 'savepairdist' specified but pairwise cache loaded from file.\n" + "Warning: Disabling 'savepairdist'.\n"); + save_pair = false; + } + } else + pairdisttype = DEFAULT_PAIRDIST_TYPE_; + + if (cache_ == 0) { + // Just 'pairdist' specified or loadpairdist specified and set/file not found. + // Warn the user. + mprintf("Warning: Pairwise distance matrix specified but cache/file '%s' not found.\n", pairdistname.c_str()); + if (!save_pair) { + // If the file (or dataset) does not yet exist we will assume we want to save. + mprintf("Warning: Pairwise distance matrix specified but not found; will save distances.\n"); + save_pair = true; + } + } + } // END if load_pair + + // Create a pairwise cache if necessary + if (cache_ == 0) { + // Process DataSet type arguments + DataSet::DataType pw_type = DataSet::PMATRIX_MEM; + std::string pw_typeString = analyzeArgs.GetStringKey("pairwisecache"); + if (!pw_typeString.empty()) { + if (pw_typeString == "mem") + pw_type = DataSet::PMATRIX_MEM; + else if (pw_typeString == "disk") { +# ifdef BINTRAJ + pw_type = DataSet::PMATRIX_NC; +# else + // TODO regular disk file option + mprinterr("Error: Pairwise disk cache requires NetCDF.\n"); + return 1; +# endif + } else if (pw_typeString == "none") + pw_type = DataSet::UNKNOWN_DATA; + else { + mprinterr("Error: Unrecognized option for 'pairwisecache' ('%s')\n", pw_typeString.c_str()); + return 1; + } + } + // Allocate cache if necessary + if (pw_type != DataSet::UNKNOWN_DATA) { + MetaData meta; + if (!pairdistname.empty()) + meta.SetName( pairdistname ); + else + meta.SetName( DSL.GenerateDefaultName("CMATRIX") ); + // Cache-specific setup. + if (pw_type == DataSet::PMATRIX_NC) + meta.SetFileName( pairdistname ); // TODO separate file name? + //cache_ = (DataSet_PairwiseCache*)DSL.AddSet( pw_type, meta, "CMATRIX" ); + // To maintain compatibility with pytraj, the cluster number vs time + // set **MUST** be allocated before the cache. Set up outside the + // DataSetList here and set up; add to DataSetList later in Setup. + cache_ = (DataSet_PairwiseCache*)DSL.AllocateSet( pw_type, meta ); + if (cache_ == 0) { + mprinterr("Error: Could not allocate pairwise cache.\n"); + return 1; + } + cacheWasAllocated_ = true; + if (debug_ > 0) + mprintf("DEBUG: Allocated pairwise distance cache: %s\n", cache_->legend()); + } + } + + // Setup pairwise matrix + //if (pmatrix_.Setup(metric_, cache_)) return 1; + + if (save_pair) { + if (cache_ == 0) { + mprintf("Warning: Not caching distances; ignoring 'savepairdist'\n"); + } else { + if (pairdistname.empty()) + pairdistname = DEFAULT_PAIRDIST_NAME_; + if (pairdisttype == DataFile::UNKNOWN_DATA) + pairdisttype = DEFAULT_PAIRDIST_TYPE_; + // TODO enable saving for other set types? + if (cache_->Type() == DataSet::PMATRIX_MEM) { + DataFile* pwd_file = DFL.AddDataFile( pairdistname, pairdisttype, ArgList() ); + if (pwd_file == 0) return 1; + pwd_file->AddDataSet( cache_ ); + if (debug_ > 0) + mprintf("DEBUG: Saving pw distance cache '%s' to file '%s'\n", cache_->legend(), + pwd_file->DataFilename().full()); + } + } + } + pw_mismatch_fatal_ = !analyzeArgs.hasKey("pwrecalc"); + + return 0; +} + +/** \return Pointer to first Metric related to COORDS, or 0 if not present. */ +Cpptraj::Cluster::Metric const* + Cpptraj::Cluster::MetricArray::CoordsMetric() const +{ + for (std::vector::const_iterator it = metrics_.begin(); it != metrics_.end(); ++it) + { + if ( (*it)->MetricType() == Metric::RMS || + (*it)->MetricType() == Metric::DME || + (*it)->MetricType() == Metric::SRMSD ) + return *it; + } + return 0; +} + +/** /return Pointer to Metric of given type. */ +Cpptraj::Cluster::Metric* Cpptraj::Cluster::MetricArray::AllocateMetric(Metric::Type mtype) +{ + Metric* met = 0; + switch (mtype) { + case Metric::RMS : met = new Metric_RMS(); break; + case Metric::DME : met = new Metric_DME(); break; + case Metric::SRMSD : met = new Metric_SRMSD(); break; + case Metric::SCALAR : met = new Metric_Scalar(); break; + case Metric::TORSION : met = new Metric_Torsion(); break; + default: mprinterr("Error: Unhandled Metric in AllocateMetric.\n"); + } + return met; +} + +/** Recognized metric args. */ +const char* Cpptraj::Cluster::MetricArray::MetricArgs_ = + "[{dme|rms|srmsd} [mass] [nofit] []] [{euclid|manhattan}] [wgt ]"; + +/** Initialize with given sets and arguments. */ +int Cpptraj::Cluster::MetricArray::initMetricArray(DataSetList const& setsToCluster, ArgList& analyzeArgs) +{ + // Get rid of any previous metrics + Clear(); + // Get arguments for any COORDS metrics + int usedme = (int)analyzeArgs.hasKey("dme"); + int userms = (int)analyzeArgs.hasKey("rms"); + int usesrms = (int)analyzeArgs.hasKey("srmsd"); + bool useMass = analyzeArgs.hasKey("mass"); + bool nofit = analyzeArgs.hasKey("nofit"); + std::string maskExpr = analyzeArgs.GetMaskNext(); + // Get other args + if (analyzeArgs.hasKey("euclid")) + type_ = EUCLID; + else if (analyzeArgs.hasKey("manhattan")) + type_ = MANHATTAN; + else { + // Default + if (setsToCluster.size() > 1) + type_ = EUCLID; + else + type_ = MANHATTAN; + } + std::string wgtArgStr = analyzeArgs.GetStringKey("wgt"); + + // Check args + if (usedme + userms + usesrms > 1) { + mprinterr("Error: Specify either 'dme', 'rms', or 'srmsd'.\n"); + return 1; + } + Metric::Type coordsMetricType; + if (usedme) coordsMetricType = Metric::DME; + else if (userms) coordsMetricType = Metric::RMS; + else if (usesrms) coordsMetricType = Metric::SRMSD; + else coordsMetricType = Metric::RMS; // default + + // For each input set, set up the appropriate metric + for (DataSetList::const_iterator ds = setsToCluster.begin(); ds != setsToCluster.end(); ++ds) + { + Metric::Type mtype = Metric::UNKNOWN_METRIC; + if ( (*ds)->Group() == DataSet::COORDINATES ) + { + mtype = coordsMetricType; + } else if ((*ds)->Group() == DataSet::SCALAR_1D) { + if ( (*ds)->Meta().IsTorsionArray() ) + mtype = Metric::TORSION; + else + mtype = Metric::SCALAR; + } + + if (mtype == Metric::UNKNOWN_METRIC) { + mprinterr("Error: Set '%s' is a type not yet supported by Cluster.\n", (*ds)->legend()); + return 1; + } + + Metric* met = AllocateMetric( mtype ); + if (met == 0) { + mprinterr("Internal Error: Could not allocate metric for set '%s'\n", (*ds)->legend()); + return 1; + } + + // Initialize the metric + int err = 0; + switch (mtype) { + case Metric::RMS : + err = ((Metric_RMS*)met)->Init((DataSet_Coords*)*ds, AtomMask(maskExpr), nofit, useMass); break; + case Metric::DME : + err = ((Metric_DME*)met)->Init((DataSet_Coords*)*ds, AtomMask(maskExpr)); break; + case Metric::SRMSD : + err = ((Metric_SRMSD*)met)->Init((DataSet_Coords*)*ds, AtomMask(maskExpr), nofit, useMass, debug_); break; + case Metric::SCALAR : + err = ((Metric_Scalar*)met)->Init((DataSet_1D*)*ds); break; + case Metric::TORSION : + err = ((Metric_Torsion*)met)->Init((DataSet_1D*)*ds); break; + default: + mprinterr("Error: Unhandled Metric setup.\n"); + err = 1; + } + if (err != 0) { + mprinterr("Error: Metric setup failed.\n"); + return 1; + } + metrics_.push_back( met ); + sets_.push_back( *ds ); + + } // END loop over input data sets + + // Process weight args if needed + if (!wgtArgStr.empty()) { + ArgList wgtArgs(wgtArgStr, ","); + // Need 1 arg for every set + if (wgtArgs.Nargs() != (int)metrics_.size()) { + mprinterr("Error: Expected %zu comma-separated args for wgt, got %i\n", + metrics_.size(), wgtArgs.Nargs()); + return 1; + } + weights_.reserve( wgtArgs.Nargs() ); + for (int arg = 0; arg != wgtArgs.Nargs(); arg++) + weights_.push_back( convertToDouble( wgtArgs[arg] ) ); + } else { + // Default weights are 1 + weights_.assign(metrics_.size(), 1.0); + } + // Temp space for calcs + temp_.assign(metrics_.size(), 0.0); + + return 0; +} + +/** Initialize metrics and pairwise cache (if needed). */ +int Cpptraj::Cluster::MetricArray::Initialize(DataSetList const& setsToCluster, + DataSetList& dslIn, DataFileList& dflIn, + ArgList& analyzeArgs, int debugIn) +{ + debug_ = debugIn; + if (initMetricArray(setsToCluster, analyzeArgs)) { + mprinterr("Error: Metric initialization failed.\n"); + return 1; + } + if (setupPairwiseCache(analyzeArgs, dslIn, dflIn)) { + mprinterr("Error: Pairwise cache initialization failed.\n"); + return 1; + } + return 0; +} + +/** Call the Setup function for all metrics. Check that size of each Metric + * is the same. + */ +int Cpptraj::Cluster::MetricArray::Setup() { + int err = 0; + ntotal_ = 0; + for (std::vector::const_iterator it = metrics_.begin(); + it != metrics_.end(); ++it) + { + if ((*it)->Setup()) { + mprinterr("Error: Metric '%s' setup failed.\n", (*it)->Description().c_str()); + err++; + } + if (ntotal_ == 0) + ntotal_ = (*it)->Ntotal(); + else { + if ( (*it)->Ntotal() != ntotal_ ) { + mprinterr("Error: Number of points covered by metric '%s' (%u) is not equal\n" + "Error: to number of points covered by metric '%s' (%u)\n", + (*it)->Description().c_str(), (*it)->Ntotal(), + metrics_.front()->Description().c_str(), metrics_.front()->Ntotal()); + return 1; + } + } + } + return err; +} + +/** Call the Info function for all metrics. */ +void Cpptraj::Cluster::MetricArray::Info() const { + static const char* DistanceTypeStr[] = { "Manhattan", "Euclidean" }; + mprintf("\tUsing %s distance.\n", DistanceTypeStr[type_]); + for (unsigned int idx = 0; idx != metrics_.size(); idx++) + { + mprintf("\tMetric %u for '%s', weight factor %g\n", + idx, sets_[idx]->legend(), weights_[idx]); + metrics_[idx]->Info(); + } + + if (cache_ == 0) + mprintf("\tPairwise distances will not be cached.\n"); + else { + if (cache_->Size() > 0) + mprintf("\tUsing existing pairwise cache: %s (%s)\n", + cache_->legend(), cache_->description()); + else + mprintf("\tPairwise distances will be cached: %s (%s)\n", + cache_->legend(), cache_->description()); + if (pw_mismatch_fatal_) + mprintf("\tCalculation will be halted if frames in cache do not match.\n"); + else + mprintf("\tPairwise distances will be recalculated if frames in cache do not match.\n"); + } +} + +// ----------------------------------------------- +/** Calculate new centroids for given list. */ +void Cpptraj::Cluster::MetricArray::NewCentroid(CentroidArray& centroids, Cframes const& framesIn) +const +{ + centroids.Clear(); + for (std::vector::const_iterator it = metrics_.begin(); it != metrics_.end(); ++it) + { + centroids.push_back( (*it)->NewCentroid( framesIn ) ); + } +} + +/** Calculate centroids in given list. */ +void Cpptraj::Cluster::MetricArray::CalculateCentroid(CentroidArray& centroids, Cframes const& framesIn) +const +{ + if (centroids.size() != metrics_.size()) { + mprinterr("Internal Error: MetricArray::CalculateCentroid: centroids and metrics_ sizes do not match.\n"); + return; + } + for (unsigned int idx = 0; idx != metrics_.size(); idx++) + metrics_[idx]->CalculateCentroid( centroids[idx], framesIn ); +} + +/** Update centroids by performing given operation between given frame and centroids. */ +void Cpptraj::Cluster::MetricArray::FrameOpCentroid(int f1, CentroidArray& centroids, + double oldSize, Metric::CentOpType OP) +const +{ + if (centroids.size() != metrics_.size()) { + mprinterr("Internal Error: MetricArray::FrameOpCentroid: centroids and metrics_ sizes do not match.\n"); + return; + } + for (unsigned int idx = 0; idx != metrics_.size(); idx++) + metrics_[idx]->FrameOpCentroid( f1, centroids[idx], oldSize, OP ); +} + +/** Manhattan distance. */ +double Cpptraj::Cluster::MetricArray::Dist_Manhattan(std::vector const& arrayIn) const { + double dist = 0.0; + for (unsigned int idx = 0; idx != arrayIn.size(); idx++) + dist += (weights_[idx] * arrayIn[idx]); + return dist; +} + +/** Euclidean distance. */ +double Cpptraj::Cluster::MetricArray::Dist_Euclidean(std::vector const& arrayIn) const { + double sumdist2 = 0.0; + for (unsigned int idx = 0; idx != arrayIn.size(); idx++) { + double dist2 = arrayIn[idx] * arrayIn[idx]; + sumdist2 += (weights_[idx] * dist2); + } + return sqrt(sumdist2); +} + +/** Perform distance calc according to current type. */ +double Cpptraj::Cluster::MetricArray::DistCalc(std::vector const& arrayIn) const { + double dist = 0; + switch (type_) { + case MANHATTAN : dist = Dist_Manhattan(arrayIn); break; + case EUCLID : dist = Dist_Euclidean(arrayIn); break; + } + return dist; +} + +/** Calculate distance between given frame and centroids. */ +double Cpptraj::Cluster::MetricArray::FrameCentroidDist(int frame, CentroidArray const& centroids ) +{ + if (centroids.size() != metrics_.size()) { + mprinterr("Internal Error: MetricArray::FrameCentroidDist: centroids and metrics_ sizes do not match.\n"); + return -1.0; + } + for (unsigned int idx = 0; idx != metrics_.size(); idx++) + temp_[idx] = metrics_[idx]->FrameCentroidDist( frame, centroids[idx] ); + return DistCalc(temp_); +} + +/** Calculate distance between given centroids. */ +double Cpptraj::Cluster::MetricArray::CentroidDist(CentroidArray const& C1, CentroidArray const& C2) +{ + if (C1.size() != metrics_.size() || C2.size() != metrics_.size()) { + mprinterr("Internal Error: MetricArray::CentroidDist: centroids and metrics_ sizes do not match.\n"); + return -1.0; + } + for (unsigned int idx = 0; idx != metrics_.size(); idx++) + temp_[idx] = metrics_[idx]->CentroidDist( C1[idx], C2[idx] ); + return DistCalc(temp_); +} + +/** \return distance between frames (uncached). */ +double Cpptraj::Cluster::MetricArray::Uncached_Frame_Distance(int f1, int f2) +{ + for (unsigned int idx = 0; idx != metrics_.size(); idx++) + temp_[idx] = metrics_[idx]->FrameDist(f1, f2); + return DistCalc(temp_); +} + +/** \return distance between frames (cached or uncached). */ +double Cpptraj::Cluster::MetricArray::Frame_Distance(int f1, int f2) { + if (cache_ != 0) + { + // TODO protect against f1/f2 out of bounds. + int idx1 = cache_->FrameToIdx()[f1]; + if (idx1 != -1) { + int idx2 = cache_->FrameToIdx()[f2]; + if (idx2 != -1) + return cache_->CachedDistance(idx1, idx2); + } + } + // If here, distance was not cached or no cache. + return Uncached_Frame_Distance(f1, f2); +} + +// ----------------------------------------------- +/** Loop over all pairs. For each distance, evaluate the contribution + * of each metric to the total distance (Manhattan). + */ +void Cpptraj::Cluster::MetricArray::CalculateMetricContributions(Cframes const& framesToCluster, + CpptrajFile& outfile) +{ + if (metrics_.size() < 2) { + mprintf("\tLess than 2 metrics; skipping metric contribution calculation.\n"); + return; + } + mprintf("\tCalculating metric contributions to total distance:\n"); + // This array will accumulate contribution fractions + std::vector> mfrac( metrics_.size() ); + // This array will accumulate contribution averages + std::vector> mavg( metrics_.size() ); + // This array will hold each contribution, adjust for distance type and weight + std::vector mcont( metrics_.size() ); + // These arrays will record the minimum and maximum distance contributions + std::vector mmin; + std::vector mmax; +// mprintf("DEBUG: %8s %8s %8s %8s", "Frame1", "Frame2", "Distance", "Sum"); // DEBUG +// for (unsigned int idx = 0; idx != metrics_.size(); idx++) // DEBUG +// mprintf(" {%8s %8s %6s}", "Raw", "Adj.", "Frac"); // DEBUG +// mprintf("\n"); // DEBUG + for (Cframes_it frm1 = framesToCluster.begin(); frm1 != framesToCluster.end(); ++frm1) + { + for (Cframes_it frm2 = frm1 + 1; frm2 != framesToCluster.end(); ++frm2) + { + // Populate the temp array + //double dist = Uncached_Frame_Distance(*frm1, *frm2); // DEBUG + Uncached_Frame_Distance(*frm1, *frm2); + // Do individual contributions, adjusted for weights and distance type + double sum = 0; + if (type_ == MANHATTAN) { + for (unsigned int idx = 0; idx != temp_.size(); idx++) { + mcont[idx] = (weights_[idx] * temp_[idx]); + sum += mcont[idx]; + } + } else if (type_ == EUCLID) { + for (unsigned int idx = 0; idx != temp_.size(); idx++) { + mcont[idx] = (weights_[idx] * (temp_[idx]*temp_[idx])); + sum += mcont[idx]; + } + } else { + // Sanity check + mprinterr("Internal Error: CalculateMetricContributions: Unhandled metric summation.\n"); + return; + } + // Do fraction contributions + for (unsigned int idx = 0; idx != temp_.size(); idx++) + mfrac[idx].accumulate( mcont[idx] / sum ); + // Set initial min/max values + if (mmin.empty()) { + mmin.resize( metrics_.size() ); + mmax.resize( metrics_.size() ); + for (unsigned int idx = 0; idx != temp_.size(); idx++) { + mmin[idx] = temp_[idx]; + mmax[idx] = temp_[idx]; + } + } + // Do averages + //mprintf("DEBUG: %8i %8i %8.3f %8.3f", *frm1 + 1, *frm2 + 1, dist, sum); // DEBUG + for (unsigned int idx = 0; idx != temp_.size(); idx++) + { + mavg[idx].accumulate( temp_[idx] ); + mmin[idx] = std::min( temp_[idx], mmin[idx] ); + mmax[idx] = std::max( temp_[idx], mmax[idx] ); + //mprintf(" {%8.3f %8.3f %6.2f}", temp_[idx], mcont[idx], mcont[idx] / sum); // DEBUG + } + //mprintf("\n"); // DEBUG + } + } + // Output + outfile.Printf("%-7s %6s %6s %12s %12s %12s %12s %s\n", + "#Metric", "FracAv", "FracSD", "Avg", "SD", "Min", "Max", "Description"); + for (unsigned int idx = 0; idx != mfrac.size(); idx++) { + outfile.Printf("%-7u %6.4f %6.4f %12.4f %12.4f %12.4f %12.4f \"%s\"\n", idx, + mfrac[idx].mean(), sqrt(mfrac[idx].variance()), + mavg[idx].mean(), sqrt(mavg[idx].variance()), + mmin[idx], mmax[idx], + metrics_[idx]->Description().c_str()); + } + outfile.Flush(); +} + +// ----------------------------------------------- +/** \return A string containing the description of all metrics. */ +std::string Cpptraj::Cluster::MetricArray::descriptionOfMetrics() const { + std::string out; + for (std::vector::const_iterator it = metrics_.begin(); + it != metrics_.end(); ++it) + { + if (it != metrics_.begin()) + out.append(","); + out.append( (*it)->Description() ); + } + return out; +} + +/** Request that distances for frames in given array be cached. + * \param framesToCache the frames to cache. + * \param sieveIn Sieve value (if any) used to generate framesToCache. This is + * purely for bookkeeping inside DataSet_PairwiseCache. + * When pw_mismatch_fatal_ is true, if a cache is present but the frames to + * cache do not match what is in the cache, exit with an error; + * otherwise recalculate the cache. + */ +int Cpptraj::Cluster::MetricArray::CacheDistances(Cframes const& framesToCache, int sieveIn) +{ + if (framesToCache.size() < 1) return 0; + // If no cache we can leave. + if (cache_ == 0) return 0; + + bool do_cache = true; + if (cache_->Size() > 0) { + do_cache = false; + mprintf("\tUsing existing cache '%s'\n", cache_->legend()); + // If cache is already populated, check that it is valid. + // The frames to cache must match cached frames. + if (!cache_->CachedFramesMatch( framesToCache )) { + if (pw_mismatch_fatal_) { + mprinterr("Error: Frames to cache do not match those in existing cache.\n"); + return 1; + } else { + mprintf("Warning: Frames to cache do not match those in existing cache.\n" + "Warning: Re-calculating pairwise cache.\n"); + do_cache = true; + } + } + // TODO Check metric? Total frames? + } + + if (do_cache) { + // Sanity check + if (metrics_.empty()) { + mprinterr("Internal Error: MetricArray::CacheDistances(): Metric is null.\n"); + return 1; + } + // Cache setup + if (cache_->SetupCache( Ntotal(), framesToCache, sieveIn, descriptionOfMetrics() )) + return 1; + // Fill cache + if (calcFrameDistances(framesToCache)) + return 1; + } + return 0; +} + +/** Cache distances between given frames using SetElement(). */ +int Cpptraj::Cluster::MetricArray::calcFrameDistances(Cframes const& framesToCache) +{ + mprintf("\tCaching distances for %zu frames.\n", framesToCache.size()); + + int f2end = (int)framesToCache.size(); + int f1end = f2end - 1; + ParallelProgress progress(f1end); + int f1, f2; + // For OMP, every other thread will need its own Cdist. + MetricArray* MyMetrics = this; +# ifdef _OPENMP +# pragma omp parallel private(MyMetrics, f1, f2) firstprivate(progress) + { + int mythread = omp_get_thread_num(); + progress.SetThread( mythread ); + if (mythread == 0) { + mprintf("\tParallelizing pairwise distance calc with %i threads\n", omp_get_num_threads()); + MyMetrics = this; + } else + MyMetrics = new MetricArray(*this); +# pragma omp for schedule(dynamic) +# endif + for (f1 = 0; f1 < f1end; f1++) { + progress.Update(f1); + for (f2 = f1 + 1; f2 < f2end; f2++) { + cache_->SetElement( f1, f2, MyMetrics->Uncached_Frame_Distance(framesToCache[f1], framesToCache[f2]) ); + } + } +# ifdef _OPENMP + if (mythread > 0) + delete MyMetrics; + } // END omp parallel +# endif + progress.Finish(); + return 0; +} diff --git a/src/Cluster/MetricArray.h b/src/Cluster/MetricArray.h new file mode 100644 index 0000000000..6d62f46f46 --- /dev/null +++ b/src/Cluster/MetricArray.h @@ -0,0 +1,124 @@ +#ifndef CPPTRAJ_CLUSTER_METRICARRAY_H +#define CPPTRAJ_CLUSTER_METRICARRAY_H +#include +#include "Metric.h" // Metric::Type +class ArgList; +class CpptrajFile; +class DataFileList; +class DataSet; +class DataSet_PairwiseCache; +class DataSetList; +namespace Cpptraj { +namespace Cluster { +class CentroidArray; +/// Hold Metrics of various types +/** This serves as the main interface for all distance calculations related + * to clustering. If using more than one metric, the total distanace will + * be accumulated as Euclidean (sqrt(SUM(d^2))) or Manhattan (SUM(d)). + */ +class MetricArray { + public: + /// CONSTRUCTOR + MetricArray(); + /// DESTRUCTOR + ~MetricArray(); + /// COPY + MetricArray(MetricArray const&); + /// ASSIGN + MetricArray& operator=(MetricArray const&); + + /// Types of distance calculation + enum DistanceType { MANHATTAN = 0, EUCLID }; + /// Recognized metric keywords + static const char* MetricArgs_; + /// Recognized pairwise keywords 1 + static const char* PairwiseArgs1_; + /// Recognized pairwise keywords 2 + static const char* PairwiseArgs2_; + + /// Initialize with sets to cluster, master data set/file lists (for cache), and user arguments + int Initialize(DataSetList const&, DataSetList&, DataFileList&, ArgList&, int); + /// Set up all metrics + int Setup(); + /// Request that the pairwise cache be filled with distances for specified frames. + int CacheDistances(Cframes const&, int); + + /// \return True if no metrics have been initialized + bool empty() const { return metrics_.empty(); } + /// Call Info() routines for all metrics + void Info() const; + /// \return Number of points covered by each Metric + unsigned int Ntotal() const { return ntotal_; } + /// \return First Metric (if any) having to do with a COORDS set + Metric const* CoordsMetric() const; + + // TODO: The CachePtr() and CacheWasAllocated() routines are only needed + // because pytraj expects the cluster # vs time set to be + // allocated *before* the cache. So it is potentially + // allocated via InitMetricArray(), but added to the master + // DataSetList later. If/when pytraj is modified to change + // this dependency, these two routines can be retired. + /// \return Pointer to internal pairwise cache. + DataSet_PairwiseCache* CachePtr() const { return cache_; } + /// \return true if cache was allocated by MetricArray + bool CacheWasAllocated() const { return cacheWasAllocated_; } + + /// \return true if there is a distance cache. + bool HasCache() const { return (cache_ != 0); } + /// \return internal cache, const. + DataSet_PairwiseCache const& Cache() const { return *cache_; } + + /// Calculate new centroid for each metric + void NewCentroid(CentroidArray&, Cframes const&) const; + /// Calculate centroids for each metric + void CalculateCentroid(CentroidArray&, Cframes const&) const; + /// Update centroids by performing given operation between given frame and centroids. + void FrameOpCentroid(int, CentroidArray&, double, Metric::CentOpType) const; + /// \return distance between given frame and centroids + double FrameCentroidDist(int, CentroidArray const&); + /// \return distance between given centroids + double CentroidDist(CentroidArray const&, CentroidArray const&); + + /// \return distance between frames (cached or uncached) + double Frame_Distance(int, int); + + /// Calculate contributions of each metric to total distance, print to given file + void CalculateMetricContributions(Cframes const&, CpptrajFile&); + private: + /// Clear array + void Clear(); + /// Set up pairwise cache + int setupPairwiseCache(ArgList&, DataSetList&, DataFileList&); + /// Allocate metric of given type + Metric* AllocateMetric(Metric::Type); + /// Initialize with data sets and user arguments + int initMetricArray(DataSetList const&, ArgList&); + /// Manhattan distance + double Dist_Manhattan(std::vector const&) const; + /// Euclidean distance + double Dist_Euclidean(std::vector const&) const; + /// Distance based on type_ + double DistCalc(std::vector const&) const; + /// \return distance between frames (uncached) + double Uncached_Frame_Distance(int, int); + + /// \return a string containing description of all metrics + std::string descriptionOfMetrics() const; + /// Fill the pairwise cache with distances for specified frames. + int calcFrameDistances(Cframes const&); + + std::vector metrics_; ///< Hold each Metric + std::vector sets_; ///< Sets corresponding to each Metric + std::vector weights_; ///< Weight of each metric + std::vector temp_; ///< For calculations; hold distances from each metric. + int debug_; ///< Debug level + DistanceType type_; ///< Type of distance calc to perform + unsigned int ntotal_; ///< Total number of points covered by any Metric + DataSet_PairwiseCache* cache_; ///< Optional cache for frame-frame distances. + bool cacheWasAllocated_; ///< True is cache was allocated by InitMetricArray() + bool pw_mismatch_fatal_; ///< Controls if PW distances should be recalculated on mismatch +}; + +} +} +#endif diff --git a/src/Cluster/Metric_DME.cpp b/src/Cluster/Metric_DME.cpp new file mode 100644 index 0000000000..c96b17125e --- /dev/null +++ b/src/Cluster/Metric_DME.cpp @@ -0,0 +1,126 @@ +#include "Metric_DME.h" +#include "Centroid_Coord.h" +#include "Cframes.h" +#include "../CpptrajStdio.h" + +/** Initialize the metric. */ +int Cpptraj::Cluster::Metric_DME::Init(DataSet_Coords* dIn, AtomMask const& maskIn) +{ + // TODO better error handles + if (dIn == 0) { + mprinterr("Internal Error: Metric_DME::Init() called with null data set.\n"); + return 1; + } +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: Init DME metric for '%s', mask '%s'\n", + dIn->legend(), maskIn.MaskString()); +# endif + coords_ = dIn; + mask_ = maskIn; + + return 0; +} + +/** Set up the metric. */ +int Cpptraj::Cluster::Metric_DME::Setup() { + if (coords_->Top().SetupIntegerMask( mask_ )) return 1; + mask_.MaskInfo(); +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: DME metric topology: %s %s %i\n", coords_->legend(), + coords_->Top().c_str(), coords_->Top().Natom()); +# endif + if (frm1_.SetupFrameFromMask(mask_, coords_->Top().Atoms())) return 1; + frm2_ = frm1_; +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: Setup DME metric for %i atoms, %zu frames.\n", frm1_.Natom(), coords_->Size()); +# endif + return 0; +} + +/** \return DME between two given frames. */ +double Cpptraj::Cluster::Metric_DME::FrameDist(int f1, int f2) { + coords_->GetFrame( f1, frm1_, mask_ ); + coords_->GetFrame( f2, frm2_, mask_ ); + return frm1_.DISTRMSD( frm2_ ); +} + +/** \return DME between two given centroids. */ +double Cpptraj::Cluster::Metric_DME::CentroidDist(Centroid* c1, Centroid* c2) { + return ((Centroid_Coord*)c1)->Cframe().DISTRMSD( ((Centroid_Coord*)c2)->Cframe() ); +} + +/** \return RMSD between given frame and centroid. */ +double Cpptraj::Cluster::Metric_DME::FrameCentroidDist(int f1, Centroid* c1) { + coords_->GetFrame( f1, frm1_, mask_ ); + return frm1_.DISTRMSD( ((Centroid_Coord*)c1)->Cframe() ); +} + +/** Compute the centroid (avg) coords for each atom from all frames in this + * cluster. NOTE: For DME the centroid should probably be calculated via + * internal coordinates; use RMS best-fit as a cheat. + */ +void Cpptraj::Cluster::Metric_DME::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { + Matrix_3x3 Rot; + Vec3 Trans; + Centroid_Coord* cent = (Centroid_Coord*)centIn; + // Reset atom count for centroid. + cent->Cframe().ClearAtoms(); + for (Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) + { + coords_->GetFrame( *frm, frm1_, mask_ ); + if (cent->Cframe().empty()) { + cent->Cframe() = frm1_; + cent->Cframe().CenterOnOrigin(false); + } else { + frm1_.RMSD_CenteredRef( cent->Cframe(), Rot, Trans, false ); + frm1_.Rotate( Rot ); + cent->Cframe() += frm1_; + } + } + cent->Cframe().Divide( (double)cframesIn.size() ); + //mprintf("\t\tFirst 3 centroid coords (of %i): %f %f %f\n", cent->Cframe().Natom(), + // cent->cent->Cframe()[0], cent->Cframe()[1],cent->Cframe()[2]); +} + +/** \return Average structure of given frames. */ +Cpptraj::Cluster::Centroid* Cpptraj::Cluster::Metric_DME::NewCentroid( Cframes const& cframesIn ) { + // TODO: Incorporate mass? + Centroid_Coord* cent = new Centroid_Coord( mask_.Nselected() ); + CalculateCentroid( cent, cframesIn ); + return cent; +} + +// Subtract Notes +// TODO: Handle single frame +// TODO: Check if frame is in cluster? +void Cpptraj::Cluster::Metric_DME::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, + CentOpType OP) +{ + Matrix_3x3 Rot; + Vec3 Trans; + Centroid_Coord* cent = (Centroid_Coord*)centIn; + coords_->GetFrame( frame, frm1_, mask_ ); + frm1_.RMSD_CenteredRef( cent->Cframe(), Rot, Trans, false ); + frm1_.Rotate( Rot ); + cent->Cframe().Multiply( oldSize ); + if (OP == ADDFRAME) { + cent->Cframe() += frm1_; + cent->Cframe().Divide( oldSize + 1 ); + } else { // SUBTRACTFRAME + cent->Cframe() -= frm1_; + cent->Cframe().Divide( oldSize - 1 ); + } +} + +/** \return Description of RMS calc. */ +std::string Cpptraj::Cluster::Metric_DME::Description() const { + return "dme " + mask_.MaskExpression(); +} + +void Cpptraj::Cluster::Metric_DME::Info() const { + mprintf("\tMetric: DME"); + if (mask_.MaskExpression() == "*") + mprintf(" (all atoms)\n"); + else + mprintf(" (mask '%s')\n", mask_.MaskString()); +} diff --git a/src/Cluster/Metric_DME.h b/src/Cluster/Metric_DME.h new file mode 100644 index 0000000000..2a6454613f --- /dev/null +++ b/src/Cluster/Metric_DME.h @@ -0,0 +1,37 @@ +#ifndef INC_CLUSTER_METRIC_DME_H +#define INC_CLUSTER_METRIC_DME_H +#include "../AtomMask.h" +#include "../DataSet_Coords.h" +#include "Metric.h" +namespace Cpptraj { +namespace Cluster { + +/// DME cluster distance calc for Coords DataSet +class Metric_DME : public Metric { + public: + Metric_DME() : Metric(DME), coords_(0) {} + int Setup(); + double FrameDist(int, int); + double CentroidDist( Centroid*, Centroid* ); + double FrameCentroidDist(int, Centroid*); + void CalculateCentroid(Centroid*, Cframes const&); + Centroid* NewCentroid(Cframes const&); + Metric* Copy() { return new Metric_DME( *this ); } + void FrameOpCentroid(int, Centroid*, double, CentOpType); + std::string Description() const; + void Info() const; + unsigned int Ntotal() const { return (unsigned int)coords_->Size(); } + // ------------------------------------------- + int Init(DataSet_Coords*, AtomMask const&); + /// \return Atom mask + AtomMask const& Mask() const { return mask_; } + private: + DataSet_Coords* coords_; + AtomMask mask_; + Frame frm1_; + Frame frm2_; +}; + +} +} +#endif diff --git a/src/Cluster/Metric_Matrix2D.cpp b/src/Cluster/Metric_Matrix2D.cpp new file mode 100644 index 0000000000..ca783138d1 --- /dev/null +++ b/src/Cluster/Metric_Matrix2D.cpp @@ -0,0 +1,31 @@ +#include "Metric_Matrix2D.h" +#include "../DataSet_2D.h" + +unsigned int Cpptraj::Cluster::Metric_Matrix2D::Ntotal() const { + return (unsigned int)matrix_->Size(); +} + +static inline void idxToColRow(int idx, int Ncols, int& col, int& row) +{ + row = idx / Ncols; + col = idx - (row * Ncols); +} + + +double Cpptraj::Cluster::Metric_Matrix2D::FrameDist(int f1, int f2) +{ + //int col, row; + //idxToColRow( f1, matrix_->Ncols(), col, row ); + double val1 = matrix_->GetElement( f1 ); + double val2 = matrix_->GetElement( f2 ); + int col1, row1; + idxToColRow( f1, matrix_->Ncols(), col1, row1 ); + int col2, row2; + idxToColRow( f2, matrix_->Ncols(), col2, row2 ); + + double dv = val1 - val2; + double dr = (double)(row1 - row2); + double dc = (double)(col1 - col2); + double dist2 = dv*dv + dr*dr + dc*dc; + return dist2; +} diff --git a/src/Cluster/Metric_Matrix2D.h b/src/Cluster/Metric_Matrix2D.h new file mode 100644 index 0000000000..e0bdc6d975 --- /dev/null +++ b/src/Cluster/Metric_Matrix2D.h @@ -0,0 +1,31 @@ +#ifndef INC_CLUSTER_METRIC_MATRIX2D_H +#define INC_CLUSTER_METRIC_MATRIX2D_H +#include "Metric.h" +class DataSet_2D; +namespace Cpptraj { +namespace Cluster { + +/// Metric for distance between two points in a matrix +class Metric_Matrix2D : public Metric { + public: + Metric_Matrix2D() : Metric(MATRIX2D), matrix_(0) {} + int Setup(); + double FrameDist(int, int); + double CentroidDist( Centroid*, Centroid* ); + double FrameCentroidDist(int, Centroid*); + void CalculateCentroid(Centroid*, Cframes const&); + Centroid* NewCentroid(Cframes const&); + Metric* Copy() { return new Metric_Matrix2D( *this ); } + void FrameOpCentroid(int, Centroid*, double, CentOpType); + std::string Description() const; + void Info() const; + unsigned int Ntotal() const; + // ------------------------------------------- + int Init(DataSet_2D*); + private: + DataSet_2D* matrix_; +}; + +} +} +#endif diff --git a/src/Cluster/Metric_RMS.cpp b/src/Cluster/Metric_RMS.cpp new file mode 100644 index 0000000000..47c8eeb01c --- /dev/null +++ b/src/Cluster/Metric_RMS.cpp @@ -0,0 +1,165 @@ +#include "Metric_RMS.h" +#include "Centroid_Coord.h" +#include "Cframes.h" +#include "../CpptrajStdio.h" + +/** Initialize the metric. */ +int Cpptraj::Cluster::Metric_RMS::Init(DataSet_Coords* dIn, AtomMask const& maskIn, + bool nofit, bool useMass) +{ + // TODO better error handles + if (dIn == 0) { + mprinterr("Internal Error: Metric_RMS::Init() called with null data set.\n"); + return 1; + } +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: Init RMS metric for '%s', mask '%s', nofit=%i, usemass=%i\n", + dIn->legend(), maskIn.MaskString(), (int)nofit, (int)useMass); +# endif + coords_ = dIn; + mask_ = maskIn; + nofit_ = nofit; + useMass_ = useMass; + + return 0; +} + +/** Set up the metric. */ +int Cpptraj::Cluster::Metric_RMS::Setup() { + if (coords_->Top().SetupIntegerMask( mask_ )) return 1; + mask_.MaskInfo(); +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: RMS metric topology: %s %s %i\n", coords_->legend(), + coords_->Top().c_str(), coords_->Top().Natom()); +# endif + if (frm1_.SetupFrameFromMask(mask_, coords_->Top().Atoms())) return 1; + frm2_ = frm1_; +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: Setup RMS metric for %i atoms, %zu frames.\n", frm1_.Natom(), coords_->Size()); +# endif + return 0; +} + +/** \return RMSD between two given frames. */ +double Cpptraj::Cluster::Metric_RMS::FrameDist(int f1, int f2) { + coords_->GetFrame( f1, frm1_, mask_ ); + coords_->GetFrame( f2, frm2_, mask_ ); +# ifdef DEBUG_CLUSTER + double rms; + frm1_.printAtomCoord(0); + frm2_.printAtomCoord(0); + if (nofit_) + rms = frm1_.RMSD_NoFit( frm2_, useMass_ ); + else + rms = frm1_.RMSD( frm2_, useMass_ ); + mprintf("\tMetric_RMS::FrameDist(%i, %i)= %g\n", f1, f2, rms); + return rms; +# else + if (nofit_) + return frm1_.RMSD_NoFit( frm2_, useMass_ ); + else + return frm1_.RMSD( frm2_, useMass_ ); +# endif +} + +/** \return RMSD between two given centroids. */ +double Cpptraj::Cluster::Metric_RMS::CentroidDist(Centroid* c1, Centroid* c2) { + if (nofit_) + return ((Centroid_Coord*)c1)->Cframe().RMSD_NoFit( ((Centroid_Coord*)c2)->Cframe(), useMass_ ); + else // Centroid is already at origin. + return ((Centroid_Coord*)c1)->Cframe().RMSD_CenteredRef( ((Centroid_Coord*)c2)->Cframe(), + useMass_ ); +} + +/** \return RMSD between given frame and centroid. */ +double Cpptraj::Cluster::Metric_RMS::FrameCentroidDist(int f1, Centroid* c1) { + coords_->GetFrame( f1, frm1_, mask_ ); + if (nofit_) + return frm1_.RMSD_NoFit( ((Centroid_Coord*)c1)->Cframe(), useMass_ ); + else // Centroid is already at origin. + return frm1_.RMSD_CenteredRef( ((Centroid_Coord*)c1)->Cframe(), useMass_ ); +} + +/** Compute the centroid (avg) coords for each atom from all frames in this + * cluster. If fitting, RMS fit to centroid as it is being built. + */ +void Cpptraj::Cluster::Metric_RMS::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { + Matrix_3x3 Rot; + Vec3 Trans; + Centroid_Coord* cent = (Centroid_Coord*)centIn; + // Reset atom count for centroid. + cent->Cframe().ClearAtoms(); + for (Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) + { + coords_->GetFrame( *frm, frm1_, mask_ ); + if (cent->Cframe().empty()) { + cent->Cframe() = frm1_; + if (!nofit_) + cent->Cframe().CenterOnOrigin(useMass_); + } else { + if (!nofit_) { + frm1_.RMSD_CenteredRef( cent->Cframe(), Rot, Trans, useMass_ ); + frm1_.Rotate( Rot ); + } + cent->Cframe() += frm1_; + } + } + cent->Cframe().Divide( (double)cframesIn.size() ); + //mprintf("\t\tFirst 3 centroid coords (of %i): %f %f %f\n", cent->Cframe().Natom(), + // cent->cent->Cframe()[0], cent->Cframe()[1],cent->Cframe()[2]); +} + +/** \return Average structure of given frames. */ +Cpptraj::Cluster::Centroid* Cpptraj::Cluster::Metric_RMS::NewCentroid( Cframes const& cframesIn ) { + // TODO: Incorporate mass? + Centroid_Coord* cent = new Centroid_Coord( mask_.Nselected() ); + CalculateCentroid( cent, cframesIn ); + return cent; +} + +// Subtract Notes +// TODO: Handle single frame +// TODO: Check if frame is in cluster? +void Cpptraj::Cluster::Metric_RMS::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, + CentOpType OP) +{ + Matrix_3x3 Rot; + Vec3 Trans; + Centroid_Coord* cent = (Centroid_Coord*)centIn; + coords_->GetFrame( frame, frm1_, mask_ ); + if (!nofit_) { + frm1_.RMSD_CenteredRef( cent->Cframe(), Rot, Trans, useMass_ ); + frm1_.Rotate( Rot ); + } + cent->Cframe().Multiply( oldSize ); + if (OP == ADDFRAME) { + cent->Cframe() += frm1_; + cent->Cframe().Divide( oldSize + 1 ); + } else { // SUBTRACTFRAME + cent->Cframe() -= frm1_; + cent->Cframe().Divide( oldSize - 1 ); + } +} + +/** \return Description of RMS calc. */ +std::string Cpptraj::Cluster::Metric_RMS::Description() const { + std::string description("rms " + mask_.MaskExpression()); + if (nofit_) description.append(" nofit"); + if (useMass_) description.append(" mass"); + return description; +} + +void Cpptraj::Cluster::Metric_RMS::Info() const { + mprintf("\tMetric: RMSD"); + if (mask_.MaskExpression() == "*") + mprintf(" (all atoms)"); + else + mprintf(" (mask '%s')", mask_.MaskString()); + if (useMass_) + mprintf(", mass-weighted"); + if (nofit_) + mprintf(", no fitting"); + else + mprintf(" best-fit"); + mprintf("\n"); +} diff --git a/src/Cluster/Metric_RMS.h b/src/Cluster/Metric_RMS.h new file mode 100644 index 0000000000..6f75051c59 --- /dev/null +++ b/src/Cluster/Metric_RMS.h @@ -0,0 +1,42 @@ +#ifndef INC_CLUSTER_METRIC_RMS_H +#define INC_CLUSTER_METRIC_RMS_H +#include "Metric.h" +#include "../AtomMask.h" +#include "../DataSet_Coords.h" +#include "../Frame.h" +namespace Cpptraj { +namespace Cluster { + +/// RMS cluster distance calc for Coords DataSet +class Metric_RMS : public Metric { + public: + Metric_RMS() : Metric(RMS), coords_(0), nofit_(false), useMass_(false) {} + int Setup(); + double FrameDist(int, int); + double CentroidDist( Centroid*, Centroid* ); + double FrameCentroidDist(int, Centroid*); + void CalculateCentroid(Centroid*, Cframes const&); + Centroid* NewCentroid(Cframes const&); + Metric* Copy() { return new Metric_RMS( *this ); } + void FrameOpCentroid(int, Centroid*, double, CentOpType); + std::string Description() const; + void Info() const; + unsigned int Ntotal() const { return (unsigned int)coords_->Size(); } + // ------------------------------------------- + int Init(DataSet_Coords*, AtomMask const&, bool, bool); + /// \return whether RMS is mass-weighted + bool UseMass() const { return useMass_; } + /// \return Atom mask + AtomMask const& Mask() const { return mask_; } + private: + DataSet_Coords* coords_; + AtomMask mask_; + bool nofit_; + bool useMass_; + Frame frm1_; + Frame frm2_; +}; + +} +} +#endif diff --git a/src/Cluster/Metric_SRMSD.cpp b/src/Cluster/Metric_SRMSD.cpp new file mode 100644 index 0000000000..936b93d5e7 --- /dev/null +++ b/src/Cluster/Metric_SRMSD.cpp @@ -0,0 +1,136 @@ +#include "Metric_SRMSD.h" +#include "Centroid_Coord.h" +#include "Cframes.h" +#include "../CpptrajStdio.h" + +int Cpptraj::Cluster::Metric_SRMSD::Init(DataSet_Coords* dIn, AtomMask const& maskIn, + bool nofit, bool useMass, int debugIn) +{ + // TODO better error handles + if (dIn == 0) { + mprinterr("Internal Error: Metric_SRMSD::Init() called with null data set.\n"); + return 1; + } + coords_ = dIn; + mask_ = maskIn; + SRMSD_.InitSymmRMSD(!nofit, useMass, debugIn); + return 0; +} + +int Cpptraj::Cluster::Metric_SRMSD::Setup() { + if (coords_->Top().SetupIntegerMask( mask_ )) return 1; + mask_.MaskInfo(); +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: SRMSD metric topology: %s %s %i\n", coords_->legend(), + coords_->Top().c_str(), coords_->Top().Natom()); +# endif + // false = no remap warning + if (SRMSD_.SetupSymmRMSD(coords_->Top(), mask_, false)) return 1; + frm1_.SetupFrameFromMask(mask_, coords_->Top().Atoms()); + frm2_ = frm1_; + return 0; +} + +double Cpptraj::Cluster::Metric_SRMSD::FrameDist(int f1, int f2) { + coords_->GetFrame( f1, frm1_, mask_ ); + coords_->GetFrame( f2, frm2_, mask_ ); + return SRMSD_.SymmRMSD(frm1_, frm2_); +} + +double Cpptraj::Cluster::Metric_SRMSD::CentroidDist(Centroid* c1, Centroid* c2) { + // Centroid is already at origin. + return SRMSD_.SymmRMSD_CenteredRef( ((Centroid_Coord*)c1)->Cframe(), + ((Centroid_Coord*)c2)->Cframe() ); +} + +double Cpptraj::Cluster::Metric_SRMSD::FrameCentroidDist(int f1, Centroid* c1) { + coords_->GetFrame( f1, frm1_, mask_ ); + // Centroid is already at origin. + return SRMSD_.SymmRMSD_CenteredRef( frm1_, ((Centroid_Coord*)c1)->Cframe() ); +} + +/** Compute the centroid (avg) coords for each atom from all frames in this + * cluster. If fitting, RMS fit to centroid as it is being built. + */ +void Cpptraj::Cluster::Metric_SRMSD::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { + Matrix_3x3 Rot; + Vec3 Trans; + Centroid_Coord* cent = (Centroid_Coord*)centIn; + // Reset atom count for centroid. + cent->Cframe().ClearAtoms(); + for (Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) + { + coords_->GetFrame( *frm, frm1_, mask_ ); + if (cent->Cframe().empty()) { + cent->Cframe() = frm1_; + if (SRMSD_.Fit()) + cent->Cframe().CenterOnOrigin(SRMSD_.UseMass()); + } else { + SRMSD_.SymmRMSD_CenteredRef( frm1_, cent->Cframe() ); + // Remap atoms + frm2_.SetCoordinatesByMap( frm1_, SRMSD_.AMap() ); + if (SRMSD_.Fit()) { + frm2_.Translate( SRMSD_.TgtTrans() ); + frm2_.Rotate( SRMSD_.RotMatrix() ); + } + cent->Cframe() += frm2_; + } + } + cent->Cframe().Divide( (double)cframesIn.size() ); + //mprintf("\t\tFirst 3 centroid coords (of %i): %f %f %f\n", cent->cframe_.Natom(), + // cent->cent->cframe_[0], cent->cframe_[1],cent->cframe_[2]); +} + +Cpptraj::Cluster::Centroid* Cpptraj::Cluster::Metric_SRMSD::NewCentroid( Cframes const& cframesIn ) { + // TODO: Incorporate mass? + Centroid_Coord* cent = new Centroid_Coord( mask_.Nselected() ); + CalculateCentroid( cent, cframesIn ); + return cent; +} + +void Cpptraj::Cluster::Metric_SRMSD::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, + CentOpType OP) +{ + Matrix_3x3 Rot; + Vec3 Trans; + Centroid_Coord* cent = (Centroid_Coord*)centIn; + coords_->GetFrame( frame, frm1_, mask_ ); + SRMSD_.SymmRMSD_CenteredRef( frm1_, cent->Cframe() ); + // Remap atoms + frm2_.SetCoordinatesByMap( frm1_, SRMSD_.AMap() ); + if (SRMSD_.Fit()) { + frm2_.Translate( SRMSD_.TgtTrans() ); + frm2_.Rotate( SRMSD_.RotMatrix() ); + } + cent->Cframe().Multiply( oldSize ); + if (OP == ADDFRAME) { + cent->Cframe() += frm2_; + cent->Cframe().Divide( oldSize + 1 ); + } else { // SUBTRACTFRAME + cent->Cframe() -= frm2_; + cent->Cframe().Divide( oldSize - 1 ); + } +} + +/** \return Description of symmetric RMS calc. */ +std::string Cpptraj::Cluster::Metric_SRMSD::Description() const { + std::string description("srmsd " + mask_.MaskExpression()); + if (!SRMSD_.Fit()) description.append(" nofit"); + if (SRMSD_.UseMass()) description.append(" mass"); + return description; +} + +void Cpptraj::Cluster::Metric_SRMSD::Info() const { + mprintf("\tMetric: Symmetric RMSD"); + if (mask_.MaskExpression() == "*") + mprintf(" (all atoms)"); + else + mprintf(" (mask '%s')", mask_.MaskString()); + if (SRMSD_.UseMass()) + mprintf(", mass-weighted"); + if (!SRMSD_.Fit()) + mprintf(", no fitting"); + else + mprintf(" best-fit"); + mprintf("\n"); +} diff --git a/src/Cluster/Metric_SRMSD.h b/src/Cluster/Metric_SRMSD.h new file mode 100644 index 0000000000..55d8f9f779 --- /dev/null +++ b/src/Cluster/Metric_SRMSD.h @@ -0,0 +1,41 @@ +#ifndef INC_CLUSTER_METRIC_SRMSD_H +#define INC_CLUSTER_METRIC_SRMSD_H +#include "Metric.h" +#include "../AtomMask.h" +#include "../DataSet_Coords.h" +#include "../SymmetricRmsdCalc.h" +namespace Cpptraj { +namespace Cluster { + +/// Symmetry-corrected RMS distance calc for Coords DataSet. +class Metric_SRMSD : public Metric { + public: + Metric_SRMSD() : Metric(SRMSD) {} + int Init(DataSet_Coords*,AtomMask const&,bool,bool,int); + /// \return whether RMSD is mass-weighted + bool UseMass() const { return SRMSD_.UseMass(); } + /// \return Atom mask + AtomMask const& Mask() const { return mask_; } + // ----- Metric ------------------------------ + int Setup(); + double FrameDist(int, int); + double CentroidDist( Centroid*, Centroid* ); + double FrameCentroidDist(int, Centroid*); + void CalculateCentroid(Centroid*, Cframes const&); + Centroid* NewCentroid(Cframes const&); + void FrameOpCentroid(int, Centroid*, double, CentOpType); + Metric* Copy() { return new Metric_SRMSD( * this ); } + std::string Description() const; + void Info() const; + unsigned int Ntotal() const { return (unsigned int)coords_->Size(); } + private: + DataSet_Coords* coords_; + AtomMask mask_; + SymmetricRmsdCalc SRMSD_; + Frame frm1_; + Frame frm2_; +}; + +} +} +#endif diff --git a/src/Cluster/Metric_Scalar.cpp b/src/Cluster/Metric_Scalar.cpp new file mode 100644 index 0000000000..6b3206a9b3 --- /dev/null +++ b/src/Cluster/Metric_Scalar.cpp @@ -0,0 +1,92 @@ +#include "Metric_Scalar.h" +#include "Centroid_Num.h" +#include "Cframes.h" +#include "../CpptrajStdio.h" +#include "../DataSet_1D.h" +#include // fabs + +/** CONSTRUCTOR */ +Cpptraj::Cluster::Metric_Scalar::Metric_Scalar() : + Metric(SCALAR), + data_(0) +{} + +/** Initialize. */ +int Cpptraj::Cluster::Metric_Scalar::Init(DataSet_1D* dataIn) { + if (dataIn == 0) { + mprinterr("Internal Error: Metric_Scalar::Init called with null set.\n"); + return 1; + } + data_ = dataIn; + return 0; +} + +/** Set up. Not much to do for a DataSet. */ +int Cpptraj::Cluster::Metric_Scalar::Setup() { + return 0; +} + +/** \return Absolute difference between points */ +double Cpptraj::Cluster::Metric_Scalar::FrameDist(int f1, int f2) { + return fabs( data_->Dval(f1) - data_->Dval(f2) ); +} + +/** \return Absolute difference between centroids. */ +double Cpptraj::Cluster::Metric_Scalar::CentroidDist(Centroid* c1, Centroid* c2) { + return fabs( ((Centroid_Num*)c1)->Cval() - ((Centroid_Num*)c2)->Cval() ); +} + +/** \return Absolute difference between point and centroid. */ +double Cpptraj::Cluster::Metric_Scalar::FrameCentroidDist(int f1, Centroid* c1) { + return fabs( data_->Dval(f1) - ((Centroid_Num*)c1)->Cval() ); +} + +/** Calculate centroid from specified frames. */ +void Cpptraj::Cluster::Metric_Scalar::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) +{ + double val = 0.0; + for (Cframes::const_iterator frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) + val += data_->Dval( *frm ); + ((Centroid_Num*)centIn)->SetCval( val / (double)cframesIn.size() ); +} + +/** \return New centroid from specified frames. */ +Cpptraj::Cluster::Centroid* + Cpptraj::Cluster::Metric_Scalar::NewCentroid(Cframes const& cframesIn) +{ + Centroid_Num* cent = new Centroid_Num(); + CalculateCentroid(cent, cframesIn); + return cent; +} + +/** Perform given operation between frame and centroid. */ +void Cpptraj::Cluster::Metric_Scalar::FrameOpCentroid(int frame, Centroid* centIn, + double oldSize, CentOpType OP) +{ + Centroid_Num* cent = (Centroid_Num*)centIn; + + double newcval = cent->Cval() * oldSize; + double fval = data_->Dval(frame); + if (OP == ADDFRAME) { + newcval += fval; + newcval /= ( oldSize + 1 ); + } else { // SUBTRACTFRAME + newcval -= fval; + newcval /= ( oldSize - 1 ); + } + + cent->SetCval( newcval ); +} + +/** \return 1 line description */ +std::string Cpptraj::Cluster::Metric_Scalar::Description() const { + return "Data set " + data_->Meta().Legend(); +} + +/** Print info to STDOUT. */ +void Cpptraj::Cluster::Metric_Scalar::Info() const { + mprintf("\tMetric: Data set type: '%s'\n", data_->description()); +} + +/** \return DataSet size */ +unsigned int Cpptraj::Cluster::Metric_Scalar::Ntotal() const { return data_->Size(); } diff --git a/src/Cluster/Metric_Scalar.h b/src/Cluster/Metric_Scalar.h new file mode 100644 index 0000000000..4e9a855c1c --- /dev/null +++ b/src/Cluster/Metric_Scalar.h @@ -0,0 +1,47 @@ +#ifndef INC_CPPTRAJ_CLUSTER_METRIC_SCALAR_H +#define INC_CPPTRAJ_CLUSTER_METRIC_SCALAR_H +#include "Metric.h" +class DataSet_1D; +namespace Cpptraj { +namespace Cluster { +/// Metric for delta between points in a regular 1D scalar DataSet. +class Metric_Scalar : public Metric { + public: + /// CONSTRUCTOR + Metric_Scalar(); + /// Initialize with DataSet + int Init(DataSet_1D*); + + // ----- Metric Routines --------------------- + /// Setup + int Setup(); + /// \return Copy of this Metric TODO const? + Metric* Copy() { return new Metric_Scalar( *this ); } + + /// \return Absolute difference between two values indicated by given indices + double FrameDist(int, int); + /// \return Absolute difference between two values of given Centroids (averages) + double CentroidDist(Centroid*, Centroid*); + /// \return Absolute difference between value indicated by index and value of centroid (average) + double FrameCentroidDist(int, Centroid*); + + /// Calculate centroid (average) from given frames. + void CalculateCentroid(Centroid*, Cframes const&); + /// \return new centroid from given frames. + Centroid* NewCentroid(Cframes const&); + /// Update centroid (average) by performing given operation between given frame and centroid. + void FrameOpCentroid(int, Centroid*, double, CentOpType); + + /// \return string containing description of the distance metric + std::string Description() const; + /// Print Metric info to stdout. + void Info() const; + /// \return total number of frames. + unsigned int Ntotal() const; + private: + DataSet_1D* data_; ///< DataSet to calculate distances for. +}; + +} +} +#endif diff --git a/src/Cluster/Metric_Torsion.cpp b/src/Cluster/Metric_Torsion.cpp new file mode 100644 index 0000000000..b50275987e --- /dev/null +++ b/src/Cluster/Metric_Torsion.cpp @@ -0,0 +1,116 @@ +#include "Metric_Torsion.h" +#include "Centroid_Num.h" +#include "Cframes.h" +#include "../Constants.h" +#include "../CpptrajStdio.h" +#include "../DataSet_1D.h" +#include // fabs, atan2 + +/** CONSTRUCTOR */ +Cpptraj::Cluster::Metric_Torsion::Metric_Torsion() : + Metric(TORSION), + data_(0) +{} + +/** Initialize. */ +int Cpptraj::Cluster::Metric_Torsion::Init(DataSet_1D* dataIn) { + if (dataIn == 0) { + mprinterr("Internal Error: Metric_Torsion::Init called with null set.\n"); + return 1; + } + data_ = dataIn; + return 0; +} + +/** Set up. Not much to do for a DataSet. */ +int Cpptraj::Cluster::Metric_Torsion::Setup() { + return 0; +} + +/// \return smallest difference between two angles (in degrees). +static inline double DistCalc_Dih(double d1, double d2) { + double diff = fabs(d1 - d2); + if (diff > 180.0) + return (360.0 - diff); + else + return diff; +} + +/** \return Shortest absolute difference between torsions */ +double Cpptraj::Cluster::Metric_Torsion::FrameDist(int f1, int f2) { + return DistCalc_Dih( data_->Dval(f1), data_->Dval(f2) ); +} + +/** \return Absolute difference between centroids. */ +double Cpptraj::Cluster::Metric_Torsion::CentroidDist(Centroid* c1, Centroid* c2) { + return DistCalc_Dih( ((Centroid_Num*)c1)->Cval(), ((Centroid_Num*)c2)->Cval() ); +} + +/** \return Absolute difference between point and centroid. */ +double Cpptraj::Cluster::Metric_Torsion::FrameCentroidDist(int f1, Centroid* c1) { + return DistCalc_Dih( data_->Dval(f1), ((Centroid_Num*)c1)->Cval() ); +} + +/** Calculate centroid from specified frames. + * Calculate unambiguous average dihedral angle (in degrees) by converting to + * cartesian coords using x = cos(theta), y = sin(theta), and: + * tan(avgtheta) = avgy / avgx = SUM[sin(theta)] / SUM[cos(theta)] + * See Eq. 2 from Altis et al., J. Chem. Phys., 126 p. 244111 (2007). + */ +void Cpptraj::Cluster::Metric_Torsion::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) +{ + double sumy = 0.0; + double sumx = 0.0; + // TODO: Convert angles to radians prior to this call? + for (Cframes::const_iterator frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) { + double theta = data_->Dval( *frm ) * Constants::DEGRAD; + sumy += sin( theta ); + sumx += cos( theta ); + } + ((Centroid_Num*)centIn)->SetCval( atan2(sumy, sumx) * Constants::RADDEG ); + ((Centroid_Num*)centIn)->SetPeriodicSums( sumx, sumy ); +} + +/** \return New centroid from specified frames. */ +Cpptraj::Cluster::Centroid* + Cpptraj::Cluster::Metric_Torsion::NewCentroid(Cframes const& cframesIn) +{ + Centroid_Num* cent = new Centroid_Num(); + CalculateCentroid(cent, cframesIn); + return cent; +} + +/** Perform given operation between frame and centroid. */ +void Cpptraj::Cluster::Metric_Torsion::FrameOpCentroid(int frame, Centroid* centIn, + double oldSize, CentOpType OP) +{ + Centroid_Num* cent = (Centroid_Num*)centIn; + + double sumx = cent->SumX(); + double sumy = cent->SumY(); + double ftheta = data_->Dval(frame) * Constants::DEGRAD; + if (OP == ADDFRAME) { + sumy += sin( ftheta ); + sumx += cos( ftheta ); + } else { // SUBTRACTFRAME + sumy -= sin( ftheta ); + sumx -= cos( ftheta ); + } + double newcval = atan2(sumy, sumx) * Constants::RADDEG; + + cent->SetCval( newcval ); + cent->SetPeriodicSums( sumx, sumy ); +} + +/** \return 1 line description */ +std::string Cpptraj::Cluster::Metric_Torsion::Description() const { + return "Torsion data set " + data_->Meta().Legend(); +} + +/** Print info to STDOUT. */ +void Cpptraj::Cluster::Metric_Torsion::Info() const { + mprintf("\tMetric: Torsion set type: '%s'\n", data_->description()); +} + +/** \return DataSet size */ +unsigned int Cpptraj::Cluster::Metric_Torsion::Ntotal() const { return data_->Size(); } diff --git a/src/Cluster/Metric_Torsion.h b/src/Cluster/Metric_Torsion.h new file mode 100644 index 0000000000..d1dd90de45 --- /dev/null +++ b/src/Cluster/Metric_Torsion.h @@ -0,0 +1,47 @@ +#ifndef INC_CPPTRAJ_CLUSTER_METRIC_TORSION_H +#define INC_CPPTRAJ_CLUSTER_METRIC_TORSION_H +#include "Metric.h" +class DataSet_1D; +namespace Cpptraj { +namespace Cluster { +/// Metric for delta between points in a 1D scalar DataSet of a torsion (360 deg.). +class Metric_Torsion : public Metric { + public: + /// CONSTRUCTOR + Metric_Torsion(); + /// Initialize with DataSet + int Init(DataSet_1D*); + + // ----- Metric Routines --------------------- + /// Setup + int Setup(); + /// \return Copy of this Metric TODO const? + Metric* Copy() { return new Metric_Torsion( *this ); } + + /// \return Absolute difference between two values indicated by given indices + double FrameDist(int, int); + /// \return Absolute difference between two values of given Centroids (averages) + double CentroidDist(Centroid*, Centroid*); + /// \return Absolute difference between value indicated by index and value of centroid (average) + double FrameCentroidDist(int, Centroid*); + + /// Calculate centroid (average) from given frames. + void CalculateCentroid(Centroid*, Cframes const&); + /// \return new centroid from given frames. + Centroid* NewCentroid(Cframes const&); + /// Update centroid (average) by performing given operation between given frame and centroid. + void FrameOpCentroid(int, Centroid*, double, CentOpType); + + /// \return string containing description of the distance metric + std::string Description() const; + /// Print Metric info to stdout. + void Info() const; + /// \return total number of frames. + unsigned int Ntotal() const; + private: + DataSet_1D* data_; ///< DataSet to calculate distances for. +}; + +} +} +#endif diff --git a/src/Cluster/Node.cpp b/src/Cluster/Node.cpp new file mode 100644 index 0000000000..9cfaf1e83f --- /dev/null +++ b/src/Cluster/Node.cpp @@ -0,0 +1,154 @@ +//#include // DBL_MAX +#include "Node.h" +#include "MetricArray.h" +#include "../DataSet_float.h" +#include "../DataSet_integer.h" + +// CONSTRUCTOR +Cpptraj::Cluster::Node::Node() : + avgSil_(0), + eccentricity_(0), + refRms_(0), + num_(-1), + needsUpdate_(true) +{} + +// DESTRUCTOR +Cpptraj::Cluster::Node::~Node() { } + +/** Create new cluster with given number containing given frames. Calculate + * initial centroid and set initial best rep frame to front, even though + * that will probably be wrong when number of frames in the list > 1. + */ +Cpptraj::Cluster::Node::Node(MetricArray& Cdist, Cframes const& frameListIn, int numIn) : + frameList_(frameListIn), + bestReps_(1, RepPair(frameListIn.front(), 0.0)), + eccentricity_(0.0), + num_(numIn), + needsUpdate_(true) +{ + Cdist.NewCentroid( centroids_, frameListIn ); +} + +// COPY CONSTRUCTOR +Cpptraj::Cluster::Node::Node(const Node& rhs) : + frameList_( rhs.frameList_ ), + centroids_(rhs.centroids_), + bestReps_( rhs.bestReps_ ), + eccentricity_( rhs.eccentricity_ ), + num_( rhs.num_ ), + needsUpdate_( rhs.needsUpdate_ ) +{ } + +// ASSIGNMENT +Cpptraj::Cluster::Node& Cpptraj::Cluster::Node::operator=(const Node& rhs) { + if (&rhs == this) return *this; + eccentricity_ = rhs.eccentricity_; + num_ = rhs.num_; + bestReps_ = rhs.bestReps_; + frameList_ = rhs.frameList_; + centroids_ = rhs.centroids_; + needsUpdate_ = rhs.needsUpdate_; + return *this; +} + +/** Calculate centroid of frames in this Node using given metric. */ +void Cpptraj::Cluster::Node::CalculateCentroid(MetricArray& Cdist) { + if (centroids_.empty()) + Cdist.NewCentroid( centroids_, frameList_ ); + else + Cdist.CalculateCentroid( centroids_, frameList_ ); +} + +/** Calculate the eccentricity of this cluster (i.e. the largest distance + * between any two points in the cluster). + */ +void Cpptraj::Cluster::Node::CalcEccentricity(MetricArray& FrameDistancesIn) { + double maxdist = 0.0; + frame_iterator frame1_end = frameList_.end(); + --frame1_end; + for (frame_iterator frm1 = frameList_.begin(); frm1 != frameList_.end(); ++frm1) + { + frame_iterator frm2 = frm1; + ++frm2; + for (; frm2 != frameList_.end(); ++frm2) { + double fdist = FrameDistancesIn.Frame_Distance(*frm1, *frm2); + if (fdist > maxdist) + maxdist = fdist; + } + } + eccentricity_ = maxdist; +} + +/** Calculate average distance between all members in cluster and + * the centroid. + */ +double Cpptraj::Cluster::Node::CalcAvgToCentroid( MetricArray& Cdist ) const +{ + double avgdist = 0.0; + //int idx = 0; // DEBUG + //mprintf("AVG DISTANCES FOR CLUSTER %d:\n", Num()); // DEBUG + for (frame_iterator frm = frameList_.begin(); frm != frameList_.end(); ++frm) + { + double dist = Cdist.FrameCentroidDist( *frm, centroids_ ); + //mprintf("\tDist to %i is %f\n", idx++, dist); // DEBUG + avgdist += dist; + } + return ( avgdist / (double)frameList_.size() ); +} + +/** Remove specified frame, update the centroid. */ +void Cpptraj::Cluster::Node::RemoveFrameUpdateCentroid(MetricArray& Cdist, int frame) { + Cdist.FrameOpCentroid(frame, centroids_, (double)frameList_.size(), + Metric::SUBTRACTFRAME); + RemoveFrameFromCluster( frame ); +} + +/** Add specified frame, update the centroid. */ +void Cpptraj::Cluster::Node::AddFrameUpdateCentroid(MetricArray& Cdist, int frame) { + Cdist.FrameOpCentroid(frame, centroids_, (double)frameList_.size(), + Metric::ADDFRAME); + AddFrameToCluster( frame ); +} + +/** Calculate cluster population vs time. */ +void Cpptraj::Cluster::Node::CalcCpopVsTime(DataSet_float& pvt, unsigned int maxFrames, + CnormType normType) +const +{ + // TODO clear pvt array? + float pop = 0.0; + // Loop over all frames in cluster + for (frame_iterator f = beginframe(); f != endframe(); ++f) + { + if (*f > (int)pvt.Size()) + pvt.Resize( *f, pop ); + pop = pop + 1.0; + pvt[*f] = pop; + } + // Ensure pop v time set is maxFrames long + if (pvt.Size() < maxFrames) + pvt.Resize( maxFrames, pop ); + // Normalization + if (normType == CLUSTERPOP) { + float norm = 1.0 / (float)Nframes(); + for (unsigned int frm = 0; frm < maxFrames; ++frm) + pvt[frm] = pvt[frm] * norm; + } else if (normType == FRAME) { + float norm = 1.0; + for (unsigned int frm = 0; frm < maxFrames; ++frm) + { + pvt[frm] = pvt[frm] / norm; + norm = norm + 1.0; + } + } +} + +/** Create cluster "lifetime" set, with 1 for cluster present and 0 for absent. */ +void Cpptraj::Cluster::Node::CreateLifetimeSet(DataSet_integer& life, unsigned int maxFrames) +const +{ + life.Resize( maxFrames ); + for (frame_iterator f = beginframe(); f != endframe(); ++f) + life.SetElement( *f, 1); +} diff --git a/src/Cluster/Node.h b/src/Cluster/Node.h new file mode 100644 index 0000000000..f2a0ef0a9a --- /dev/null +++ b/src/Cluster/Node.h @@ -0,0 +1,147 @@ +#ifndef INC_CLUSTER_NODE_H +#define INC_CLUSTER_NODE_H +#include +#include // std::pair +#include +#include "CentroidArray.h" +#include "Cframes.h" // Cframes::const_iterator +class DataSet_integer; +class DataSet_float; +namespace Cpptraj { +namespace Cluster { +class MetricArray; +// TODO implement needsUpdate_ + +/// Hold frame indices for a given cluster. +class Node { + public: + Node(); + ~Node(); + // NOTE: Taking a non-const reference to Metric here allows + // MetricArray to be passed in as const to routines while still + // allowing Metric to be used. Metric needs to be non-const because + // things like calculating RMSD modify Metric itself to avoid + // always reallocating Frames. + /// CONSTRUCTOR - Take Metric for calculating centroid, frames, and cluster index. + Node(MetricArray&, Cframes const&, int); + /// COPY CONSTRUCTOR + Node(const Node&); + /// ASSIGNMENT + Node& operator=(const Node&); + + /// Types of normalization for cluster pop v time. + enum CnormType { NONE = 0, CLUSTERPOP, FRAME }; + + /// Used to pair a representative frame number with a score. + typedef std::pair RepPair; + /// Used to hold a list of representative frames/scores + typedef std::vector RepPairArray; + /// Used to pair frame numbers with silhouette values. + typedef std::pair SilPair; + /// Used to hold list of frame numbers/silhouette values. + typedef std::vector SilPairArray; + + /// Used to sort clusters by # of frames in cluster + inline bool operator<(const Node&) const; + /// Find and set frame in the cluster that has lowest distance to all other frames. +// int SetBestRep_CumulativeDist(DataSet_Cmatrix const&); + /// Calculate average distance of all members to centroid + double CalcAvgToCentroid(MetricArray&) const; + /// Const iterator over frame numbers + typedef Cframes::const_iterator frame_iterator; + /// Const iterator to beginning of frames + frame_iterator beginframe() const { return frameList_.begin(); } + /// Const iteratir to end of frames. + frame_iterator endframe() const { return frameList_.end(); } + /// \return Frame number at given index. + int ClusterFrame(int idx) const { return frameList_[idx]; } + /// \return cluster eccentricity + double Eccentricity() const { return eccentricity_; } + /// \return internal cluster number + int Num() const { return num_; } + /// \return number of frames in cluster. + int Nframes() const { return (int)frameList_.size(); } + /// \return best representative frame number, or -1 if no best rep set. + int BestRepFrame() const { + if (bestReps_.empty()) + return -1; + else + return bestReps_.front().first; + } + /// \return Cluster centroid array. + CentroidArray const& Cent() const { return centroids_; } + /// \return name assigned via reference + std::string const& Cname() const { return name_; } + /// \return RMS to reference + double RefRms() const { return refRms_; } + /// \return true if given frame is in this cluster. + bool HasFrame(int f) const { return frameList_.HasFrame(f); } + /// Access representative frame list, const + RepPairArray const& BestReps() const { return bestReps_; } + /// Access frame silhouette list + SilPairArray const& FrameSilhouettes() const { return frameSil_; } + /// \return cluster silhoueete vaule + double Silhouette() const { return avgSil_; } + + /// Calculate centroid of members of this cluster. + void CalculateCentroid(MetricArray&); + /// Add frame to cluster + void AddFrameToCluster(int fnum) { frameList_.push_back( fnum ); } + /// Set cluster number (for bookkeeping). + void SetNum(int numIn) { num_ = numIn; } + /// Access representative frame list + RepPairArray& BestReps() { return bestReps_; } + /// Access frame silhouette list + SilPairArray& FrameSilhouettes() { return frameSil_; } + /// Set cluster silhouette value + void SetSilhouette(double s) { avgSil_ = s; } + /// Sort internal frame list + void SortFrameList() { frameList_.Sort(); } + /// Remove specified frame from cluster if present. + void RemoveFrameFromCluster(int f) { frameList_.Remove(f); } + /// Merge frames from another cluster to this cluster + inline void MergeFrames(Node const&); + /// Set cluster name and RMS to reference + inline void SetNameAndRms(std::string const&, double); + /// Calculate eccentricity for frames in this cluster. + void CalcEccentricity(MetricArray&); + /// Remove specified frame from cluster and update centroid. + void RemoveFrameUpdateCentroid(MetricArray&, int); + /// Add specified frame to cluster and update centroid. + void AddFrameUpdateCentroid(MetricArray&, int); + + /// Calculate cluster population vs time. + void CalcCpopVsTime(DataSet_float&, unsigned int, CnormType) const; + /// Create cluster lifetime set. + void CreateLifetimeSet(DataSet_integer&, unsigned int) const; + private: + Cframes frameList_; ///< List of frames belonging to this cluster. + CentroidArray centroids_; ///< Centroids (1 for each metric) for all frames in this cluster. + std::string name_; ///< Cluster name assigned from reference. + RepPairArray bestReps_; ///< Hold best representative frames and their score. + SilPairArray frameSil_; ///< Frame silhouette values. + double avgSil_; ///< Average silhouette value for cluster TODO s.d. as well? + double eccentricity_; ///< Maximum distance between any 2 frames. + double refRms_; ///< Cluster rms to reference (if assigned). + int num_; ///< Cluster number, used for bookkeeping. + bool needsUpdate_; ///< True if internal metrics need updating (e.g. after frames added). +}; +// ----- INLINE FUNCTIONS ------------------------------------------------------ +/** Use > since we give higher priority to larger clusters. */ +bool Node::operator<(const Node& rhs) const { + return ( frameList_.size() > rhs.frameList_.size() ); +} +/** Frames from rhs go to this cluster. */ +void Node::MergeFrames( Node const& rhs) { + frameList_.Insert( rhs.frameList_ ); + //frameList_.insert(frameList_.end(), rhs.frameList_.begin(), rhs.frameList_.end()); +} +/** Set reference name and RMS. */ +void Node::SetNameAndRms(std::string const& nameIn, double rmsIn) { + name_ = nameIn; + refRms_ = rmsIn; +} + +} /* END namespace Cluster */ +} /* END namespace Cpptraj */ +#endif diff --git a/src/Cluster/Output.cpp b/src/Cluster/Output.cpp new file mode 100644 index 0000000000..c58c9a0ab6 --- /dev/null +++ b/src/Cluster/Output.cpp @@ -0,0 +1,442 @@ +#include // sqrt +#include // sort, max +#include "Output.h" +#include "Algorithm.h" +#include "BestReps.h" +#include "List.h" +#include "MetricArray.h" +#include "Node.h" +#include "../Matrix.h" +#include "../CpptrajFile.h" +#include "../CpptrajStdio.h" + +// XMGRACE colors +const char* XMGRACE_COLOR[] = { + "white", "black", "red", "green", "blue", "yellow", "brown", "grey", "violet", + "cyan", "magenta", "orange", "indigo", "maroon", "turquoise", "darkgreen" +}; + +// ----------------------------------------------------------------------------- +// ClusterList::PrintClustersToFile() +/** Print list of clusters in a style similar to ptraj; each cluster is + * given a line maxframes characters long, with X for each frame that is + * in the clusters and . for all other frames. Also print out the + * representative frame numbers. + */ +void Cpptraj::Cluster::Output::PrintClustersToFile(CpptrajFile& outfile, + List const& clusters, + Algorithm const& algorithmIn, + MetricArray& metricIn, int sieve, + Cframes const& sievedFrames) +{ + //CpptrajFile outfile; + std::string buffer; + + /*if ( outfile.OpenWrite(filename) ) { + mprinterr("Error: PrintClustersToFile: Could not set up file %s\n", + filename.c_str()); + return; + }*/ + outfile.Printf("#Clustering: %i clusters %u frames\n", + clusters.Nclusters(), metricIn.Ntotal()); + // DBI + std::vector averageDist; + double DBITotal = clusters.ComputeDBI( averageDist, metricIn ); + std::vector::const_iterator avgd = averageDist.begin(); + for (List::cluster_iterator C = clusters.begincluster(); + C != clusters.endcluster(); + ++C, ++avgd) + outfile.Printf("#Cluster %i has average-distance-to-centroid %f\n", C->Num(), *avgd); + outfile.Printf("#DBI: %f\n", DBITotal); + // Pseudo-F + if (clusters.Nclusters() > 1) { + double SSRSST = 0.0; + double pseudof = clusters.ComputePseudoF( SSRSST, metricIn ); + outfile.Printf("#pSF: %f\n", pseudof); + outfile.Printf("#SSR/SST: %f\n", SSRSST); + } else + mprintf("Warning: Fewer than 2 cluster. Not calculating pseudo-F.\n"); + + // Call internal info routine. + algorithmIn.Results( outfile ); + // Print noise frames. + if (clusters.Noise().size() > 0) { + outfile.Printf("#NOISE_FRAMES:"); + unsigned int numNoise = 0; + for (Cframes::const_iterator frm = clusters.Noise().begin(); + frm != clusters.Noise().end(); ++frm) + { + outfile.Printf(" %i", *frm+1); + ++numNoise; + } + outfile.Printf("\n"); + outfile.Printf("#Number_of_noise_frames: %u\n", numNoise); + } + // Do not print trajectory stuff if no filename given (i.e. STDOUT output) + if (!outfile.IsStream()) { + for (List::cluster_iterator C1 = clusters.begincluster(); C1 != clusters.endcluster(); ++C1) + { + buffer.clear(); + buffer.resize(metricIn.Ntotal(), '.'); + for (Node::frame_iterator f1 = C1->beginframe(); f1 != C1->endframe(); ++f1) + buffer[ *f1 ] = 'X'; + buffer += '\n'; + outfile.Write((void*)buffer.c_str(), buffer.size()); + } + } + // Print representative frame numbers + outfile.Printf("#Representative frames:"); + for (List::cluster_iterator C1 = clusters.begincluster(); C1 != clusters.endcluster(); ++C1) + if (C1->BestReps().size() < 2) + outfile.Printf(" %i", C1->BestRepFrame()+1); + else { + outfile.Printf(" {"); + for (Node::RepPairArray::const_iterator rep = C1->BestReps().begin(); + rep != C1->BestReps().end(); ++rep) + outfile.Printf(" %i %g", rep->first+1, rep->second); + outfile.Printf(" }"); + } + outfile.Printf("\n"); + // Print sieve info if present + if (sieve != 1) { + if (sieve < -1) { + outfile.Printf("#Sieve value: %i (random)\n#Sieved frames:", -sieve); + for (Cframes::const_iterator sfrm = sievedFrames.begin(); + sfrm != sievedFrames.end(); ++sfrm) + outfile.Printf(" %i", *sfrm + 1); + outfile.Printf("\n"); + } else + outfile.Printf("#Sieve value: %i\n", sieve); + } + outfile.CloseFile(); +} + +/// For sorting cluster frame silhouettes by silhouette value. +struct sort_by_sil_val { + typedef Cpptraj::Cluster::Node::SilPair Bpair; + inline bool operator()(Bpair const& p0, Bpair const& p1) + { + if (p0.second == p1.second) + return (p0.first < p1.first); + else + return (p0.second < p1.second); + } +}; + +/** Print cluster silhouette frame values, sorted by silhouette. */ +int Cpptraj::Cluster::Output::PrintSilhouetteFrames(CpptrajFile& Ffile, List const& clusters) +{ + // TODO different ways of writing out cluster frame silhouettes + unsigned int idx = 0; + for (List::cluster_iterator Ci = clusters.begincluster(); + Ci != clusters.endcluster(); ++Ci, ++idx) + { + Ffile.Printf("#C%-6i %10s\n", Ci->Num(), "Silhouette"); + Node::SilPairArray spaTemp = Ci->FrameSilhouettes(); + std::sort( spaTemp.begin(), spaTemp.end(), sort_by_sil_val() ); + for (Node::SilPairArray::const_iterator it = spaTemp.begin(); + it != spaTemp.end(); ++it, ++idx) + Ffile.Printf("%8u %g\n", idx, it->second); + Ffile.Printf("\n"); + } + return 0; +} + +/** Print average cluster silhouette values. */ +int Cpptraj::Cluster::Output::PrintSilhouettes(CpptrajFile& Cfile, List const& clusters) +{ + // TODO is it ok to assume clusters are in order? + Cfile.Printf("%-8s %10s\n", "#Cluster", ""); + for (List::cluster_iterator Ci = clusters.begincluster(); + Ci != clusters.endcluster(); ++Ci) + Cfile.Printf("%8i %g\n", Ci->Num(), Ci->Silhouette()); + return 0; +} + +/** Quick pass through clusters to determine max width of cluster names. */ +unsigned int Cpptraj::Cluster::Output::DetermineNameWidth(List const& clusters) +{ + unsigned int nWidth = 0; + for (List::cluster_iterator node = clusters.begincluster(); + node != clusters.endcluster(); ++node) + nWidth = std::max(nWidth, (unsigned int)node->Cname().size()); + return nWidth; +} + +/** Print a summary of clusters. */ +int Cpptraj::Cluster::Output::Summary(CpptrajFile& outfile, List const& clusters, + Algorithm const& algorithm, + MetricArray& pmatrix, + bool includeSieved, bool includeSieveCdist, + Cframes const& sievedOut) +{ + double fmax = (double)pmatrix.Ntotal(); + //if (FrameDistances().SieveValue() != 1 && !includeSieveInAvg) + // mprintf("Warning: Within cluster average distance (AvgDist) does not include sieved frames.\n"); + outfile.Printf("%-8s %8s %8s %8s %8s","#Cluster","Frames","Frac", "AvgDist","Stdev"); + if (!clusters.empty() && clusters.front().BestReps().size() > 1) { + int nBestReps = clusters.front().BestReps().size(); + for (int i = 0; i != nBestReps; i++) + outfile.Printf(" %8s %8s", "Rep", "RepScore"); + } else + outfile.Printf(" %8s", "Centroid"); + outfile.Printf(" %8s", "AvgCDist"); + unsigned int nWidth = DetermineNameWidth(clusters); + if (nWidth > 0) { + if (nWidth < 8) nWidth = 8; + outfile.Printf(" %*s %8s", nWidth, "Name", "RMS"); + } + outfile.Printf("\n"); + //Timer t_fdist; // DEBUG + //Timer t_cdist; // DEBUG + //t_cdist.Start(); + // Calculate distances between clusters. + Matrix cluster_distances; + cluster_distances.resize( 0, clusters.Nclusters() ); + for (List::cluster_iterator c1 = clusters.begincluster(); c1 != clusters.endcluster(); ++c1) + for (List::cluster_iterator c2 = c1; c2 != clusters.endcluster(); ++c2) + if (c2 != c1) + cluster_distances.addElement( algorithm.ClusterDistance( *c1, *c2, pmatrix, + includeSieveCdist, sievedOut ) ); + //t_cdist.Stop(); + + unsigned int idx1 = 0; + for (List::cluster_iterator node = clusters.begincluster(); + node != clusters.endcluster(); ++node, ++idx1) + { + // Calculate the average distance of this cluster to every other cluster. + //t_cdist.Start(); + double avgclusterdist = 0.0; + if (clusters.Nclusters() > 1) { + unsigned int idx2 = 0; + for (List::cluster_iterator node2 = clusters.begincluster(); + node2 != clusters.endcluster(); ++node2, ++idx2) + { + if (node != node2) + avgclusterdist += cluster_distances.element(idx1, idx2); + } + avgclusterdist /= (double)(clusters.Nclusters() - 1); + //mprintf("CLUSTER %i avgclusterdist= %g\n", node->Num(), avgclusterdist); + } + //t_cdist.Stop(); + // Since there may be a lot of frames do not calculate SD from the + // mean (which requires either storing distances or two double loops), + // instead use SD = sqrt( (SUM[x^2] - ((SUM[x])^2)/N)/N ) + //t_fdist.Start(); + double internalAvg = 0.0; + double internalSD = 0.0; + unsigned int Nelements = 0; + if (node->Nframes() > 1) { + // Calculate average distance between all frames in this cluster. + if (includeSieved) { + for (Node::frame_iterator f1 = node->beginframe(); f1 != node->endframe(); ++f1) { + for (Node::frame_iterator f2 = f1 + 1; f2 != node->endframe(); ++f2) { + double dist = pmatrix.Frame_Distance(*f1, *f2); + internalAvg += dist; + internalSD += (dist * dist); + ++Nelements; + } + } + } else { + for (Node::frame_iterator f1 = node->beginframe(); f1 != node->endframe(); ++f1) { + if (!sievedOut.HasFrame( *f1 )) { + for (Node::frame_iterator f2 = f1 + 1; f2 != node->endframe(); ++f2) { + if (!sievedOut.HasFrame( *f2 )) { + double dist = pmatrix.Frame_Distance(*f1, *f2); + internalAvg += dist; + internalSD += (dist * dist); + ++Nelements; + } + } + } + } + } + if (Nelements > 0) { + double norm = 1.0 / ((double)Nelements); + internalAvg *= norm; + internalSD *= norm; + internalSD -= (internalAvg * internalAvg); + if (internalSD > 0.0) + internalSD = sqrt( internalSD ); + else + internalSD = 0.0; + } + //t_fdist.Stop(); + } + // OUTPUT - TODO handle case when clusters dont have same number best reps + outfile.Printf("%8i %8i %8.3f %8.3f %8.3f", + node->Num(), node->Nframes(), (double)node->Nframes()/fmax, + internalAvg, internalSD); + if (node->BestReps().size() < 2) + outfile.Printf(" %8i", node->BestRepFrame()+1); + else { + for (Node::RepPairArray::const_iterator rep = node->BestReps().begin(); + rep != node->BestReps().end(); ++rep) + outfile.Printf(" %8i %8.3f", rep->first+1, rep->second); + } + outfile.Printf(" %8.3f", avgclusterdist); + if (nWidth > 0) + outfile.Printf(" %*s %8.3f", nWidth, node->Cname().c_str(), node->RefRms()); + outfile.Printf("\n"); + } // END loop over clusters + //t_cdist.WriteTiming(1, "Between-cluster distance calc."); + //t_fdist.WriteTiming(1, "Within-cluster distance calc."); + return 0; +} + +/** Cluster summary by parts. */ +void Cpptraj::Cluster::Output::Summary_Part(CpptrajFile& outfile, + unsigned int clusterDataSetSize, + Cframes const& splitFrames, + List const& clusters, + BestReps const& findBestReps, + MetricArray& pmatrix, + Cframes const& framesToCluster) +{ + // If no split frames were specified, use halfway point. + Cframes actualSplitFrames; + if (splitFrames.empty()) + actualSplitFrames.push_back( clusterDataSetSize / 2 ); + else { + // Check that none of the split values are invalid. + for (Cframes::const_iterator f = splitFrames.begin(); + f != splitFrames.end(); ++f) + if ( *f < 1 || *f >= (int)clusterDataSetSize ) + mprintf("Warning: split frame %i is out of bounds; ignoring.\n", *f); + else + actualSplitFrames.push_back( *f ); + } + + const char* nExt[] = {"st", "nd", "rd", "th"}; + if (actualSplitFrames.empty()) return; // Sanity check. + double fmax = (double)clusterDataSetSize; + + // Determine number of frames and traj offset for each part. + outfile.Printf("# 1st"); + std::vector partMax; + partMax.reserve( actualSplitFrames.size() + 1 ); + std::vector trajOffset; + trajOffset.reserve( actualSplitFrames.size() + 1); + trajOffset.push_back( 0 ); + int lastMax = 0; + unsigned int eidx = 1; + for (unsigned int sf = 0; sf < actualSplitFrames.size(); sf++) + { + partMax.push_back( (double)(actualSplitFrames[sf] - lastMax) ); + lastMax = actualSplitFrames[sf]; + trajOffset.push_back( lastMax ); + outfile.Printf(" <= %i < %u%s", trajOffset.back(), sf+2, nExt[eidx]); + if (eidx < 3) ++eidx; + } + partMax.push_back( (double)(clusterDataSetSize - lastMax) ); + outfile.Printf("\n# "); + // Print # of frames in each section + eidx=0; + for (std::vector::const_iterator pm = partMax.begin(); pm != partMax.end(); ++pm) { + if (pm != partMax.begin()) outfile.Printf(" "); + outfile.Printf("%li%s= %.0f", pm - partMax.begin() + 1, nExt[eidx], *pm); + if (eidx < 3) ++eidx; + } + outfile.Printf("\n"); + // DEBUG + //mprintf("DEBUG: # Frames (offset):"); + //std::vector::const_iterator of = trajOffset.begin(); + //for (std::vector::const_iterator it = partMax.begin(); + // it != partMax.end(); ++it, ++of) + // mprintf(" %.0f (%i)", *it, *of); + //mprintf("\n"); + // Set up bins + std::vector numInPart( actualSplitFrames.size() + 1, 0 ); + std::vector firstFrame( actualSplitFrames.size() + 1, -1); + + // Header + outfile.Printf("#%-7s %8s %8s %2s %10s", "Cluster", "Total", "Frac", "C#", "Color"); + eidx = 0; + for (unsigned int pm = 1; pm <= partMax.size(); ++pm) { + outfile.Printf(" %5s%u%2s", "NumIn", pm, nExt[eidx]); + if (eidx < 3) ++eidx; + } + for (unsigned int pm = 1; pm <= partMax.size(); ++pm) + outfile.Printf(" %7s%u", "Frac", pm); + for (unsigned int pm = 1; pm <= partMax.size(); ++pm) + outfile.Printf(" %7s%u", "First", pm); + // Best reps header + for (unsigned int pm = 1; pm <= partMax.size(); ++pm) + outfile.Printf(" %7s%u", "Rep", pm); + // Determine if cluster names will be output. + unsigned int nWidth = DetermineNameWidth(clusters); + if (nWidth > 0) { + if (nWidth < 8) nWidth = 8; + outfile.Printf(" %*s %6s", nWidth, "Name", "RMS"); + } + // END HEADER + outfile.Printf("\n"); + + // LOOP OVER CLUSTERS + int color = 1; // xmgrace color, 1-15 + for (List::cluster_iterator node = clusters.begincluster(); + node != clusters.endcluster(); ++node) + { + // Calculate size and fraction of total size of this cluster + int numframes = node->Nframes(); + double frac = (double)numframes / fmax; + std::fill( numInPart.begin(), numInPart.end(), 0 ); + std::fill( firstFrame.begin(), firstFrame.end(), -1 ); + std::vector clusterPart(actualSplitFrames.size() + 1); + // DEBUG + //mprintf("\tCluster %i\n",node->num); + // Count how many frames are in each part. + for (Node::frame_iterator frame1 = node->beginframe(); + frame1 != node->endframe(); + frame1++) + { + unsigned int bin = actualSplitFrames.size(); + for (unsigned int sf = 0; sf < actualSplitFrames.size(); ++sf) { + if ( *frame1 < actualSplitFrames[sf] ) { + bin = sf; + break; + } + } + if (numInPart[ bin ] == 0) + firstFrame[ bin ] = *frame1 - trajOffset[ bin ] + 1; + ++numInPart[ bin ]; + clusterPart[bin].AddFrameToCluster(*frame1); + } + outfile.Printf("%-8i %8i %8.4f %2i %10s", node->Num(), numframes, frac, + color, XMGRACE_COLOR[color]); + for (std::vector::const_iterator np = numInPart.begin(); + np != numInPart.end(); ++np) + outfile.Printf(" %8i", *np); + for (unsigned int pm = 0; pm < partMax.size(); ++pm) + outfile.Printf(" %8.4f", ((double)numInPart[pm]) / partMax[pm]); + for (std::vector::const_iterator ff = firstFrame.begin(); + ff != firstFrame.end(); ++ff) + outfile.Printf(" %8i", *ff); + // Print best reps for each part. + // TODO handle case when clusters dont have same number best reps + for (std::vector::iterator node = clusterPart.begin(); + node != clusterPart.end(); ++node) + { + if (node->Nframes() == 0) { + outfile.Printf(" %8i", -1); + } else { + findBestReps.FindBestRepFrames(*node, pmatrix, framesToCluster); + // TODO handle multiple best reps? + //if (node->BestReps().size() < 2) + outfile.Printf(" %8i", node->BestRepFrame()+1); + //else { + // for (Node::RepPairArray::const_iterator rep = node->BestReps().begin(); + // rep != node->BestReps().end(); ++rep) + // outfile.Printf(" %8i %8.3f", rep->first+1, rep->second); + //} + } + } + // Cluster name from assignrefs + if (nWidth > 0) + outfile.Printf(" %*s %6.2f", nWidth, node->Cname().c_str(), node->RefRms()); + // END LINE + outfile.Printf("\n"); + if (color<15) ++color; + } + outfile.CloseFile(); +} diff --git a/src/Cluster/Output.h b/src/Cluster/Output.h new file mode 100644 index 0000000000..2491710327 --- /dev/null +++ b/src/Cluster/Output.h @@ -0,0 +1,28 @@ +#ifndef INC_CLUSTER_OUTPUT_H +#define INC_CLUSTER_OUTPUT_H +class CpptrajFile; +namespace Cpptraj { +namespace Cluster { +class Algorithm; +class Cframes; +class List; +class MetricArray; +class BestReps; +/// Cluster output routines. +class Output { + public: + static void PrintClustersToFile(CpptrajFile&, List const&, Algorithm const&, MetricArray&, + int, Cframes const&); + static int PrintSilhouetteFrames(CpptrajFile&, List const&); + static int PrintSilhouettes(CpptrajFile&, List const&); + static int Summary(CpptrajFile&, List const&, Algorithm const&, MetricArray&, + bool, bool, Cframes const&); + static void Summary_Part(CpptrajFile&, unsigned int, Cframes const&, List const&, + BestReps const&, MetricArray&, Cframes const&); + private: + static unsigned int DetermineNameWidth(List const&); +}; + +} +} +#endif diff --git a/src/Cluster/Results.h b/src/Cluster/Results.h new file mode 100644 index 0000000000..9677d06d29 --- /dev/null +++ b/src/Cluster/Results.h @@ -0,0 +1,27 @@ +#ifndef INC_CLUSTER_RESULTS_H +#define INC_CLUSTER_RESULTS_H +class ArgList; +class DataSetList; +namespace Cpptraj { +namespace Cluster { +class List; +class MetricArray; +/// Abstract base class for handling results specific to input data type. +class Results { + public: + enum Type { COORDS = 0 }; + + Results(Type t) : type_(t) {} + virtual ~Results() {} + + virtual int GetOptions(ArgList&, DataSetList const&, MetricArray const&) = 0; + virtual void Info() const = 0; + virtual int DoOutput(List const&) const = 0; + virtual int CalcResults(List&) const = 0; + private: + Type type_; +}; + +} +} +#endif diff --git a/src/Cluster/Results_Coords.cpp b/src/Cluster/Results_Coords.cpp new file mode 100644 index 0000000000..9dec0c6ffd --- /dev/null +++ b/src/Cluster/Results_Coords.cpp @@ -0,0 +1,380 @@ +#include "Results_Coords.h" +#include "List.h" +#include "Metric_DME.h" +#include "Metric_RMS.h" +#include "Metric_SRMSD.h" +#include "MetricArray.h" +#include "Node.h" +#include "../ArgList.h" +#include "../CpptrajStdio.h" +#include "../DataSet_Coords.h" +#include "../DataSetList.h" // For PrepareTrajWrite +#include "../StringRoutines.h" +#include "../Trajout_Single.h" + +/** The default output trajectory format. */ +const TrajectoryFile::TrajFormatType Cpptraj::Cluster::Results_Coords::DEF_TRAJ_FMT_ = + TrajectoryFile::AMBERTRAJ; + +/// CONSTRUCTOR +Cpptraj::Cluster::Results_Coords::Results_Coords(DataSet_Coords* ds) : + Results(COORDS), + coords_(ds), + writeRepFrameNum_(false), + clusterfmt_(TrajectoryFile::UNKNOWN_TRAJ), + singlerepfmt_(TrajectoryFile::UNKNOWN_TRAJ), + reptrajfmt_(TrajectoryFile::UNKNOWN_TRAJ), + avgfmt_(TrajectoryFile::UNKNOWN_TRAJ) +{} + +/** Help for Results_Coords keywords. */ +void Cpptraj::Cluster::Results_Coords::Help() { + mprintf("\t[clusterout [clusterfmt ]]\n" + "\t[singlerepout [singlerepfmt ]]\n" + "\t[repout [repfmt ] [repframe]]\n" + "\t[avgout [avgfmt ]]\n" + "\t[assignrefs [refcut ] [refmask ]]\n"); +} + +/** Get arguments related to writing cluster data to trajectories. */ +void Cpptraj::Cluster::Results_Coords::GetClusterTrajArgs(ArgList& argIn, + const char* trajKey, const char* fmtKey, + std::string& trajName, + TrajectoryFile::TrajFormatType& fmt) const +{ + trajName = argIn.GetStringKey( trajKey ); + fmt = TrajectoryFile::WriteFormatFromString( argIn.GetStringKey(fmtKey), fmt ); + // If file name specified but not format, try to guess from name + if (!trajName.empty() && fmt == TrajectoryFile::UNKNOWN_TRAJ) + fmt = TrajectoryFile::WriteFormatFromFname( trajName, DEF_TRAJ_FMT_ ); +} + +/** Get user specified options. */ +int Cpptraj::Cluster::Results_Coords::GetOptions(ArgList& analyzeArgs, DataSetList const& DSL, + MetricArray const& metricIn) +{ + writeRepFrameNum_ = analyzeArgs.hasKey("repframe"); + GetClusterTrajArgs(analyzeArgs, "clusterout", "clusterfmt", clusterfile_, clusterfmt_); + GetClusterTrajArgs(analyzeArgs, "singlerepout", "singlerepfmt", singlerepfile_, singlerepfmt_); + GetClusterTrajArgs(analyzeArgs, "repout", "repfmt", reptrajfile_, reptrajfmt_); + GetClusterTrajArgs(analyzeArgs, "avgout", "avgfmt", avgfile_, avgfmt_); + + if (analyzeArgs.hasKey("assignrefs")) { + refSets_ = DSL.GetSetsOfType("*", DataSet::REF_FRAME); + if (refSets_.empty()) { + mprinterr("Error: 'assignrefs' specified but no references loaded.\n"); + return 1; + } + refCut_ = analyzeArgs.getKeyDouble("refcut", 1.0); + refmaskexpr_ = analyzeArgs.GetStringKey("refmask"); + useMass_ = false; + // Attempt to set defaults from Metric if applicable + Metric const* coordsMetric = metricIn.CoordsMetric(); + if (coordsMetric != 0) { + if (coordsMetric->MetricType() == Metric::RMS) { + Metric_RMS const& met = static_cast( *coordsMetric ); + useMass_ = met.UseMass(); + if (refmaskexpr_.empty()) refmaskexpr_ = met.Mask().MaskString(); + } else if (coordsMetric->MetricType() == Metric::SRMSD) { + Metric_SRMSD const& met = static_cast( *coordsMetric ); + useMass_ = met.UseMass(); + if (refmaskexpr_.empty()) refmaskexpr_ = met.Mask().MaskString(); + } else if (coordsMetric->MetricType() == Metric::DME) { + Metric_DME const& met = static_cast( *coordsMetric ); + if (refmaskexpr_.empty()) refmaskexpr_ = met.Mask().MaskString(); + } + } + // Set a default mask if needed + if (refmaskexpr_.empty()) { + refmaskexpr_.assign("!@H="); + mprintf("Warning: 'assignrefs' specified but no 'refmask' given.\n" + "Warning: Using default mask expression: '%s'\n", refmaskexpr_.c_str()); + } + } + + return 0; +} + +/** Write info on what results will be calculated/written. */ +void Cpptraj::Cluster::Results_Coords::Info() const { + if (coords_ == 0) { + mprintf("\tNo coordinates set provided for cluster results.\n"); + return; + } + + mprintf("\tCoordinates set for cluster results: %s\n", coords_->legend()); + if (!clusterfile_.empty()) + mprintf("\tCluster trajectories will be written to %s, format %s\n", + clusterfile_.c_str(), TrajectoryFile::FormatString(clusterfmt_)); + if (!singlerepfile_.empty()) + mprintf("\tCluster representatives will be written to 1 traj (%s), format %s\n", + singlerepfile_.c_str(), TrajectoryFile::FormatString(singlerepfmt_)); + if (!reptrajfile_.empty()) { + mprintf("\tCluster representatives will be written to separate trajectories,\n"); + mprintf("\t\tprefix (%s), format %s",reptrajfile_.c_str(), + TrajectoryFile::FormatString(reptrajfmt_)); + if (writeRepFrameNum_) mprintf(", with frame #s"); + mprintf("\n"); + } + if (!avgfile_.empty()) + mprintf("\tAverage structures for clusters will be written to %s, format %s\n", + avgfile_.c_str(), TrajectoryFile::FormatString(avgfmt_)); + + if (!refSets_.empty()) + mprintf("\tClusters will be identified with loaded reference structures if RMSD\n" + "\t (mask '%s') to representative frame is < %g Ang.\n", + refmaskexpr_.c_str(), refCut_); +} + +/** Do any output needed. */ +int Cpptraj::Cluster::Results_Coords::DoOutput(List const& CList) const { + int err = 0; + // Write clusters to trajectories + if (!clusterfile_.empty()) + WriteClusterTraj( CList ); + // Write all representative frames to a single traj + if (!singlerepfile_.empty()) + WriteSingleRepTraj( CList ); + // Write all representative frames to separate trajs + if (!reptrajfile_.empty()) + WriteRepTraj( CList ); + // Write average structures for each cluster to separate files. + if (!avgfile_.empty()) + WriteAvgStruct( CList ); + return err; +} + +/** Calculate any results that belong in clusters. */ +int Cpptraj::Cluster::Results_Coords::CalcResults(List& CList) const { + int err = 0; + // Assign reference structures to clusters + if (!refSets_.empty()) + err += AssignRefsToClusters( CList ); + return err; +} + +/** Write frames in each cluster to a trajectory file. */ +void Cpptraj::Cluster::Results_Coords::WriteClusterTraj( List const& CList ) const { + Topology* clusterparm = coords_->TopPtr(); + // Loop over all clusters + for (List::cluster_iterator C = CList.begincluster(); + C != CList.endcluster(); ++C) + { + // Create filename based on cluster number. + int cnum = C->Num(); + std::string cfilename = clusterfile_ + ".c" + integerToString( cnum ); + // Set up trajectory file + Trajout_Single clusterout; + if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), clusterparm, + coords_->CoordsInfo(), C->Nframes(), + clusterfmt_)) + { + mprinterr("Error: Could not set up cluster trajectory %s for write.\n", + cfilename.c_str()); + return; + } + // Loop over all frames in cluster + int set = 0; + Frame clusterframe = coords_->AllocateFrame(); + for (Node::frame_iterator fnum = C->beginframe(); + fnum != C->endframe(); ++fnum) + { + coords_->GetFrame( *fnum, clusterframe ); + clusterout.WriteSingle(set++, clusterframe); + } + // Close traj + clusterout.EndTraj(); + } +} + +/** Write average of clusters to files. */ +void Cpptraj::Cluster::Results_Coords::WriteAvgStruct( List const& CList ) const { + Topology avgparm = coords_->Top(); + // Get extension for representative frame format + std::string tmpExt = TrajectoryFile::WriteFormatExtension(avgfmt_); + // Loop over all clusters + for (List::cluster_iterator C = CList.begincluster(); + C != CList.endcluster(); ++C) + { + // Create filename based on cluster number. + int cnum = C->Num(); + std::string cfilename = avgfile_ + ".c" + integerToString( cnum ) + tmpExt; + // Set up trajectory file + Trajout_Single clusterout; // FIXME CoordinateInfo OK for just coords? + if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), &avgparm, + CoordinateInfo(), 1, avgfmt_)) + { + mprinterr("Error: Could not set up cluster average file %s for write.\n", + cfilename.c_str()); + return; + } + // Get rep frame for rms fitting. + Frame repframe = coords_->AllocateFrame(); + coords_->GetFrame( C->BestRepFrame(), repframe ); + Vec3 reftrans = repframe.CenterOnOrigin(false); + // Loop over all frames in cluster + Frame clusterframe = coords_->AllocateFrame(); + Frame avgframe = clusterframe; + avgframe.ZeroCoords(); + for (Node::frame_iterator fnum = C->beginframe(); + fnum != C->endframe(); ++fnum) + { + coords_->GetFrame( *fnum, clusterframe ); + clusterframe.RMSD_FitToRef( repframe, reftrans ); + avgframe += clusterframe; + } + avgframe.Divide( (double)C->Nframes() ); + clusterout.WriteSingle(0, avgframe); + clusterout.EndTraj(); + } +} + +/** Write representative frame of each cluster to a trajectory file. */ +void Cpptraj::Cluster::Results_Coords::WriteSingleRepTraj( List const& CList ) const { + Trajout_Single clusterout; + // Set up trajectory file. Use parm from COORDS DataSet. + Topology *clusterparm = coords_->TopPtr(); + int nRepsToSave = CList.front().BestReps().size(); + if (clusterout.PrepareTrajWrite(singlerepfile_, ArgList(), DataSetList(), clusterparm, + coords_->CoordsInfo(), CList.Nclusters() * nRepsToSave, + singlerepfmt_)) + { + mprinterr("Error: Could not set up single trajectory for represenatatives %s for write.\n", + singlerepfile_.c_str()); + return; + } + // Set up frame to hold cluster rep coords. + Frame clusterframe = coords_->AllocateFrame(); + int framecounter = 0; + // Write rep frames from all clusters. + for (List::cluster_iterator cluster = CList.begincluster(); + cluster != CList.endcluster(); ++cluster) + { + for (Node::RepPairArray::const_iterator rep = cluster->BestReps().begin(); + rep != cluster->BestReps().end(); ++rep) + { + coords_->GetFrame( rep->first, clusterframe ); + clusterout.WriteSingle(framecounter++, clusterframe); + } + } + // Close traj + clusterout.EndTraj(); +} + +/** Write representative frame of each cluster to a separate trajectory file, + * repfile.REPNUM.FMT + */ +void Cpptraj::Cluster::Results_Coords::WriteRepTraj( List const& CList ) const { + // Get extension for representative frame format + std::string tmpExt = TrajectoryFile::WriteFormatExtension(reptrajfmt_); + // Use Topology from COORDS DataSet to set up input frame + Topology* clusterparm = coords_->TopPtr(); + Frame clusterframe = coords_->AllocateFrame(); + // Loop over all clusters + for (List::cluster_iterator C = CList.begincluster(); + C != CList.endcluster(); ++C) + { + if (writeRepFrameNum_) { + // Each rep from cluster to separate file. + for (Node::RepPairArray::const_iterator rep = C->BestReps().begin(); + rep != C->BestReps().end(); ++rep) + { + Trajout_Single clusterout; + // Get best rep frame # + int framenum = rep->first; + // Create filename based on cluster number and frame # + std::string cfilename = reptrajfile_ + ".c" + integerToString(C->Num()) + + ("." + integerToString(framenum+1)) + tmpExt; + // Set up trajectory file. + if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), clusterparm, + coords_->CoordsInfo(), 1, reptrajfmt_)) + { + mprinterr("Error: Could not set up representative trajectory file %s for write.\n", + cfilename.c_str()); + return; + } + // Write cluster rep frame + coords_->GetFrame( framenum, clusterframe ); + clusterout.WriteSingle(framenum, clusterframe); + // Close traj + clusterout.EndTraj(); + } + } else { + // Each rep from cluster to single file. + Trajout_Single clusterout; + // Create filename based on cluster number + std::string cfilename = reptrajfile_ + ".c" + integerToString(C->Num()) + tmpExt; + // Set up trajectory file. + int nRepsToSave = C->BestReps().size(); + if (clusterout.PrepareTrajWrite(cfilename, ArgList(), DataSetList(), clusterparm, + coords_->CoordsInfo(), nRepsToSave, reptrajfmt_)) + { + mprinterr("Error: Could not set up representative trajectory file %s for write.\n", + cfilename.c_str()); + return; + } + int framecounter = 0; + for (Node::RepPairArray::const_iterator rep = C->BestReps().begin(); + rep != C->BestReps().end(); ++rep) + { + // Write cluster rep frame + coords_->GetFrame( rep->first, clusterframe ); + clusterout.WriteSingle( framecounter++, clusterframe ); + } + // Close traj + clusterout.EndTraj(); + } + } +} + +/** Assign reference frames to clusters via closest RMSD. */ +int Cpptraj::Cluster::Results_Coords::AssignRefsToClusters( List& CList ) +const +{ + // Pre-center all reference coords at the origin. No need to store trans vectors. + std::vector refFrames; + refFrames.reserve( refSets_.size() ); + for (unsigned int idx = 0; idx != refSets_.size(); idx++) { + AtomMask rMask( refmaskexpr_ ); + DataSet_Coords_REF* REF_ds = (DataSet_Coords_REF*)refSets_[idx]; + if ( REF_ds->Top().SetupIntegerMask( rMask, REF_ds->RefFrame() ) ) { + mprintf("Warning: Could not set up mask for reference '%s'\n", REF_ds->legend()); + continue; + } + refFrames.push_back( Frame(REF_ds->RefFrame(), rMask) ); + refFrames.back().CenterOnOrigin( useMass_ ); + } + // For each cluster, assign the reference name with the lowest RMSD + // to the representative frame that is below the cutoff. + AtomMask tMask( refmaskexpr_ ); + if (coords_->Top().SetupIntegerMask( tMask )) { + mprinterr("Error: Could not set up mask for assigning references.\n"); + return 1; + } + Frame TGT( coords_->AllocateFrame(), tMask ); + unsigned int cidx = 0; + for (List::cluster_it cluster = CList.begin(); + cluster != CList.end(); ++cluster, ++cidx) + { + coords_->GetFrame( cluster->BestRepFrame(), TGT, tMask ); + double minRms = TGT.RMSD_CenteredRef( refFrames[0], useMass_ ); + unsigned int minIdx = 0; + for (unsigned int idx = 1; idx < refSets_.size(); idx++) { + double rms = TGT.RMSD_CenteredRef( refFrames[idx], useMass_ ); + if (rms < minRms) { + minRms = rms; + minIdx = idx; + } + } + if (minRms < refCut_) { + //mprintf("DEBUG: Assigned cluster %i to reference \"%s\" (%g)\n", cidx, + // refSets_[minIdx]->Meta().Name().c_str(), minRms); + cluster->SetNameAndRms( refSets_[minIdx]->Meta().Name(), minRms ); + } else { + //mprintf("DEBUG: Cluster %i was closest to reference \"(%s)\" (%g)\n", cidx, + // refSets_[minIdx]->Meta().Name().c_str(), minRms); + cluster->SetNameAndRms( "(" + refSets_[minIdx]->Meta().Name() + ")", minRms ); + } + } + return 0; +} diff --git a/src/Cluster/Results_Coords.h b/src/Cluster/Results_Coords.h new file mode 100644 index 0000000000..076fd80516 --- /dev/null +++ b/src/Cluster/Results_Coords.h @@ -0,0 +1,51 @@ +#ifndef INC_CLUSTER_RESULTS_COORDS_H +#define INC_CLUSTER_RESULTS_COORDS_H +#include "Results.h" +#include "../DataSetList.h" // for assignrefs +#include "../TrajectoryFile.h" +class DataSet_Coords; +namespace Cpptraj { +namespace Cluster { + +/// Class for handling cluster results specific to COORDS input data. +class Results_Coords : public Results { + public: + Results_Coords(DataSet_Coords*); + static void Help(); + // ----- Results functions ------------------- + int GetOptions(ArgList&, DataSetList const&, MetricArray const&); + void Info() const; + int DoOutput(List const&) const; + int CalcResults(List&) const; + private: + void GetClusterTrajArgs(ArgList&, const char*, const char*, std::string&, + TrajectoryFile::TrajFormatType&) const; + void WriteClusterTraj( List const& ) const; + void WriteAvgStruct( List const& ) const; + void WriteSingleRepTraj( List const& ) const; + void WriteRepTraj( List const& ) const; + + int AssignRefsToClusters(List&) const; + + static const TrajectoryFile::TrajFormatType DEF_TRAJ_FMT_; + + DataSet_Coords* coords_; ///< The COORDS data set + bool writeRepFrameNum_; ///< If true frame #s will be in rep file names. + TrajectoryFile::TrajFormatType clusterfmt_; ///< Cluster trajectory format. + TrajectoryFile::TrajFormatType singlerepfmt_; ///< Cluster all rep single trajectory format. + TrajectoryFile::TrajFormatType reptrajfmt_; ///< Cluster rep to separate trajectory format. + TrajectoryFile::TrajFormatType avgfmt_; ///< Cluster traj average structure file format. + std::string clusterfile_; ///< Cluster trajectory base filename. + std::string singlerepfile_; ///< Cluster all rep single trajectory filename. + std::string reptrajfile_; ///< Cluster rep to separate trajectory filename. + std::string avgfile_; ///< Cluster traj average structure filename. + + DataSetList refSets_; ///< Hold reference frames to compare to + std::string refmaskexpr_; ///< Select atoms to compare in ref frames and cluster reps + double refCut_; ///< RMSD cutoff for assigning refs in Ang. + bool useMass_; ///< Whether to mass-weight RMS or not, based on metric +}; + +} +} +#endif diff --git a/src/Cluster/Sieve.cpp b/src/Cluster/Sieve.cpp new file mode 100644 index 0000000000..aa95b8afeb --- /dev/null +++ b/src/Cluster/Sieve.cpp @@ -0,0 +1,106 @@ +#include "Sieve.h" +#include "../DataSet_PairwiseCache.h" +#include "../Random.h" + +void Cpptraj::Cluster::Sieve::DetermineTypeFromSieve( int sieveIn ) { + sieve_ = sieveIn; + // Determine sieve type from sieve value. + if (sieve_ < -1) + type_ = RANDOM; + else if (sieve_ < 2) { + type_ = NONE; + sieve_ = 1; + } else + type_ = REGULAR; +} + +/** Setup which frames should be clustered.*/ +int Cpptraj::Cluster::Sieve::SetFramesToCluster(int sieveIn, std::size_t maxFrames, int iseed) +{ + // Sanity check. Should never be called with maxFrames < 1 + if (maxFrames < 1) return 1; + DetermineTypeFromSieve( sieveIn ); + framesToCluster_.clear(); + sievedOut_.clear(); + // --------------------------------------------- + if (type_ == NONE) + { + // No sieving; frame == index + framesToCluster_.reserve( maxFrames ); + for (unsigned int i = 0; i < maxFrames; i++) + framesToCluster_.push_back( i ); + } + // --------------------------------------------- + else if (type_ == REGULAR) + { + // Regular sieveing; index = frame / sieve + framesToCluster_.reserve( maxFrames / sieve_ + 1 ); + sievedOut_.reserve( maxFrames - (maxFrames / sieve_) ); + unsigned int tgt = 0; + for (unsigned int i = 0; i < maxFrames; i++) + { + if (i == tgt) { + framesToCluster_.push_back( i ); + tgt += sieve_; + } else + sievedOut_.push_back( i ); + } + } + // --------------------------------------------- + else if (type_ == RANDOM) + { + // Random sieving; maxframes / sieve random indices + Cframes frameToIdx( maxFrames, -1 ); + framesToCluster_.reserve( maxFrames / sieve_ + 1 ); + sievedOut_.reserve( maxFrames - (maxFrames / sieve_) ); + unsigned int maxidx = maxFrames - 1; + Random_Number random; + random.rn_set( iseed ); + for (unsigned int i = 0; i < maxFrames; i -= sieve_) + { + bool frame_generated = false; + // Pick until we pick a frame that has not yet been selected. + while (!frame_generated) { + unsigned int iframe = random.rn_num_interval(0, maxidx); + if (frameToIdx[iframe] == -1) { + frameToIdx[iframe] = 1; + frame_generated = true; + } + } + } + // Put indices in order + for (unsigned int i = 0; i < maxFrames; i++) + if (frameToIdx[i] == 1) + framesToCluster_.push_back( i ); + else + sievedOut_.push_back( i ); + } + // --------------------------------------------- +// MakeIdxToFrame(); + return 0; +} + +/** Set frames to cluster and sieved out frames from pairwise cache. */ +int Cpptraj::Cluster::Sieve::SetupFromCache(DataSet_PairwiseCache const& cache, + std::size_t maxFrames) +{ + if (cache.Size() < 1) { + //mprinterr("Error: Cannot setup frames to cluster from empty cache.\n"); + return 1; + } + framesToCluster_.clear(); + sievedOut_.clear(); + DetermineTypeFromSieve( cache.SieveVal() ); + unsigned int frm = 0; + for (; frm != cache.FrameToIdx().size(); frm++) + { + if (cache.FrameToIdx()[frm] == -1) + sievedOut_.push_back( frm ); + else + framesToCluster_.push_back( frm ); + } + // Anything left is consiedered sieved out. + for (; frm < maxFrames; frm++) + sievedOut_.push_back( frm ); + return 0; +} diff --git a/src/Cluster/Sieve.h b/src/Cluster/Sieve.h new file mode 100644 index 0000000000..6a7878773b --- /dev/null +++ b/src/Cluster/Sieve.h @@ -0,0 +1,33 @@ +#ifndef INC_CLUSTER_SIEVE_H +#define INC_CLUSTER_SIEVE_H +#include "Cframes.h" +class DataSet_PairwiseCache; +namespace Cpptraj { +namespace Cluster { + +/// Hold frames to be clustered and frames to be sieved out. +class Sieve { + public: + enum SieveType { NONE=0, REGULAR, RANDOM }; + + Sieve() : type_(NONE), sieve_(1) {} + + int SetFramesToCluster(int, std::size_t, int); + int SetupFromCache( DataSet_PairwiseCache const&, std::size_t ); + void Clear() { framesToCluster_.clear(); sievedOut_.clear(); type_ = NONE; sieve_ = 1; } + + Cframes const& FramesToCluster() const { return framesToCluster_; } + Cframes const& SievedOut() const { return sievedOut_; } + int SieveValue() const { return sieve_; } + private: + void DetermineTypeFromSieve(int); + + Cframes framesToCluster_; ///< Frames to cluster. + Cframes sievedOut_; ///< Frames that will not be clustered (i.e. sieved out). + SieveType type_; ///< Sieveing type. + int sieve_; ///< Sieving value. +}; + +} +} +#endif diff --git a/src/Cluster/clusterdepend b/src/Cluster/clusterdepend new file mode 100644 index 0000000000..cf51e1e619 --- /dev/null +++ b/src/Cluster/clusterdepend @@ -0,0 +1,25 @@ +Algorithm.o : Algorithm.cpp ../CpptrajStdio.h Algorithm.h CentroidArray.h Cframes.h Metric.h MetricArray.h Node.h +Algorithm_DBscan.o : Algorithm_DBscan.cpp ../ArgList.h ../ArrayIterator.h ../AssociatedData.h ../Atom.h ../AtomMask.h ../AtomType.h ../BaseIOtype.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataFile.h ../DataSet.h ../DataSetList.h ../DataSet_2D.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../DataSet_MatrixDbl.h ../Dimension.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../MaskToken.h ../Matrix.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../ProgressBar.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../StringRoutines.h ../SymbolExporting.h ../TextFormat.h ../Timer.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h Algorithm.h Algorithm_DBscan.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Node.h +Algorithm_DPeaks.o : Algorithm_DPeaks.cpp ../ArgList.h ../AssociatedData.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_1D.h ../DataSet_Mesh.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../Parallel.h ../ProgressBar.h ../Range.h ../Spline.h ../TextFormat.h Algorithm.h Algorithm_DPeaks.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Node.h +Algorithm_HierAgglo.o : Algorithm_HierAgglo.cpp ../ArgList.h ../ArrayIterator.h ../CpptrajFile.h ../CpptrajStdio.h ../FileIO.h ../FileName.h ../Matrix.h ../Parallel.h ../ProgressBar.h ../Timer.h Algorithm.h Algorithm_HierAgglo.h CentroidArray.h Cframes.h DynamicMatrix.h List.h Metric.h MetricArray.h Node.h +Algorithm_Kmeans.o : Algorithm_Kmeans.cpp ../ArgList.h ../CpptrajFile.h ../CpptrajStdio.h ../FileIO.h ../FileName.h ../Parallel.h ../ProgressBar.h ../Random.h Algorithm.h Algorithm_Kmeans.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Node.h +BestReps.o : BestReps.cpp ../CpptrajStdio.h BestReps.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Node.h +CentroidArray.o : CentroidArray.cpp Centroid.h CentroidArray.h +Centroid_Coord.o : Centroid_Coord.cpp ../Atom.h ../AtomMask.h ../Box.h ../CoordinateInfo.h ../CpptrajFile.h ../FileIO.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../Molecule.h ../NameType.h ../Parallel.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../Unit.h ../Vec3.h Centroid.h Centroid_Coord.h +Cframes.o : Cframes.cpp Cframes.h +Cmatrix_Binary.o : Cmatrix_Binary.cpp ../CpptrajFile.h ../CpptrajStdio.h ../FileIO.h ../FileName.h ../Parallel.h Cframes.h Cmatrix_Binary.h +Cmatrix_NC.o : Cmatrix_NC.cpp ../CpptrajStdio.h ../FileName.h ../NC_Routines.h Cframes.h Cmatrix_NC.h +Control.o : Control.cpp ../ArgList.h ../ArrayIterator.h ../AssociatedData.h ../Atom.h ../AtomMask.h ../AtomType.h ../BaseIOtype.h ../Box.h ../BufferedLine.h ../Cluster/Cframes.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataFile.h ../DataFileList.h ../DataSet.h ../DataSetList.h ../DataSet_1D.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../DataSet_PairwiseCache.h ../DataSet_float.h ../DataSet_integer.h ../Dimension.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../MaskToken.h ../Matrix.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Random.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../TextFormat.h ../Timer.h ../Topology.h ../TrajectoryFile.h ../TypeNameHolder.h ../Unit.h ../Vec3.h Algorithm.h Algorithm_DBscan.h Algorithm_DPeaks.h Algorithm_HierAgglo.h Algorithm_Kmeans.h BestReps.h CentroidArray.h Cframes.h Control.h DrawGraph.h DynamicMatrix.h List.h Metric.h MetricArray.h Node.h Output.h Results.h Results_Coords.h Sieve.h +DrawGraph.o : DrawGraph.cpp ../AssociatedData.h ../Atom.h ../Constants.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_1D.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../NameType.h ../PDBfile.h ../Parallel.h ../Range.h ../Residue.h ../SymbolExporting.h ../TextFormat.h ../Vec3.h Cframes.h DrawGraph.h Metric.h MetricArray.h +DynamicMatrix.o : DynamicMatrix.cpp ../ArrayIterator.h ../CpptrajStdio.h ../Matrix.h DynamicMatrix.h +List.o : List.cpp ../AssociatedData.h ../Constants.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_1D.h ../DataSet_integer.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../Parallel.h ../ProgressBar.h ../Range.h ../TextFormat.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Node.h +MetricArray.o : MetricArray.cpp ../ArgList.h ../ArrayIterator.h ../AssociatedData.h ../Atom.h ../AtomMap.h ../AtomMask.h ../AtomType.h ../BaseIOtype.h ../Box.h ../Cluster/Cframes.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataFile.h ../DataFileList.h ../DataSet.h ../DataSetList.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../DataSet_PairwiseCache.h ../Dimension.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../Hungarian.h ../MapAtom.h ../MaskToken.h ../Matrix.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../OnlineVarT.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../ProgressBar.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../StringRoutines.h ../SymbolExporting.h ../SymmetricRmsdCalc.h ../TextFormat.h ../Timer.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h CentroidArray.h Metric.h MetricArray.h Metric_DME.h Metric_RMS.h Metric_SRMSD.h Metric_Scalar.h Metric_Torsion.h +Metric_DME.o : Metric_DME.cpp ../AssociatedData.h ../Atom.h ../AtomMask.h ../AtomType.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_Coords.h ../Dimension.h ../FileIO.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../TextFormat.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h Centroid.h Centroid_Coord.h Cframes.h Metric.h Metric_DME.h +Metric_RMS.o : Metric_RMS.cpp ../AssociatedData.h ../Atom.h ../AtomMask.h ../AtomType.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_Coords.h ../Dimension.h ../FileIO.h ../FileName.h ../Frame.h ../MaskToken.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../TextFormat.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h Centroid.h Centroid_Coord.h Cframes.h Metric.h Metric_RMS.h +Metric_SRMSD.o : Metric_SRMSD.cpp ../ArrayIterator.h ../AssociatedData.h ../Atom.h ../AtomMap.h ../AtomMask.h ../AtomType.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_Coords.h ../Dimension.h ../FileIO.h ../FileName.h ../Frame.h ../Hungarian.h ../MapAtom.h ../MaskToken.h ../Matrix.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../SymbolExporting.h ../SymmetricRmsdCalc.h ../TextFormat.h ../Topology.h ../TypeNameHolder.h ../Unit.h ../Vec3.h Centroid.h Centroid_Coord.h Cframes.h Metric.h Metric_SRMSD.h +Metric_Scalar.o : Metric_Scalar.cpp ../AssociatedData.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_1D.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../Parallel.h ../Range.h ../TextFormat.h Centroid.h Centroid_Num.h Cframes.h Metric.h Metric_Scalar.h +Metric_Torsion.o : Metric_Torsion.cpp ../AssociatedData.h ../Constants.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSet_1D.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../Parallel.h ../Range.h ../TextFormat.h Centroid.h Centroid_Num.h Cframes.h Metric.h Metric_Torsion.h +Node.o : Node.cpp ../AssociatedData.h ../CpptrajFile.h ../DataSet.h ../DataSet_1D.h ../DataSet_float.h ../DataSet_integer.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../Parallel.h ../Range.h ../TextFormat.h CentroidArray.h Cframes.h Metric.h MetricArray.h Node.h +Output.o : Output.cpp ../ArrayIterator.h ../CpptrajFile.h ../CpptrajStdio.h ../FileIO.h ../FileName.h ../Matrix.h ../Parallel.h Algorithm.h BestReps.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Node.h Output.h +Results_Coords.o : Results_Coords.cpp ../ActionFrameCounter.h ../ArgList.h ../ArrayIterator.h ../AssociatedData.h ../Atom.h ../AtomMap.h ../AtomMask.h ../AtomType.h ../BaseIOtype.h ../Box.h ../Constants.h ../CoordinateInfo.h ../CpptrajFile.h ../CpptrajStdio.h ../DataSet.h ../DataSetList.h ../DataSet_Coords.h ../DataSet_Coords_REF.h ../Dimension.h ../FileIO.h ../FileName.h ../FileTypes.h ../Frame.h ../Hungarian.h ../MapAtom.h ../MaskToken.h ../Matrix.h ../Matrix_3x3.h ../MetaData.h ../Molecule.h ../NameType.h ../OutputTrajCommon.h ../Parallel.h ../ParameterHolders.h ../ParameterSet.h ../ParameterTypes.h ../Range.h ../ReferenceFrame.h ../ReplicaDimArray.h ../Residue.h ../Segment.h ../StringRoutines.h ../SymbolExporting.h ../SymmetricRmsdCalc.h ../TextFormat.h ../Timer.h ../Topology.h ../TrajectoryFile.h ../Trajout_Single.h ../TypeNameHolder.h ../Unit.h ../Vec3.h CentroidArray.h Cframes.h List.h Metric.h MetricArray.h Metric_DME.h Metric_RMS.h Metric_SRMSD.h Node.h Results.h Results_Coords.h +Sieve.o : Sieve.cpp ../AssociatedData.h ../Cluster/Cframes.h ../CpptrajFile.h ../DataSet.h ../DataSet_PairwiseCache.h ../Dimension.h ../FileIO.h ../FileName.h ../MetaData.h ../Parallel.h ../Random.h ../Range.h ../TextFormat.h Cframes.h Sieve.h diff --git a/src/Cluster/clusterfiles b/src/Cluster/clusterfiles new file mode 100644 index 0000000000..fbdd6c0e17 --- /dev/null +++ b/src/Cluster/clusterfiles @@ -0,0 +1,28 @@ +# Files related to new clustering code +CLUSTER_SOURCES= \ + Algorithm.cpp \ + Algorithm_DBscan.cpp \ + Algorithm_DPeaks.cpp \ + Algorithm_HierAgglo.cpp \ + Algorithm_Kmeans.cpp \ + BestReps.cpp \ + Centroid_Coord.cpp \ + CentroidArray.cpp \ + Cframes.cpp \ + Cmatrix_Binary.cpp \ + Cmatrix_NC.cpp \ + Control.cpp \ + DrawGraph.cpp \ + DynamicMatrix.cpp \ + List.cpp \ + MetricArray.cpp \ + Metric_DME.cpp \ + Metric_RMS.cpp \ + Metric_Scalar.cpp \ + Metric_SRMSD.cpp \ + Metric_Torsion.cpp \ + Node.cpp \ + Output.cpp \ + Results_Coords.cpp \ + Sieve.cpp + diff --git a/src/ClusterDist.cpp b/src/ClusterDist.cpp deleted file mode 100644 index 79d3683f90..0000000000 --- a/src/ClusterDist.cpp +++ /dev/null @@ -1,534 +0,0 @@ -#include -#include "ClusterDist.h" -#include "Constants.h" // RADDEG, DEGRAD -// TODO: All DataSet stuff const& - -void Centroid_Coord::Print(std::string const& fnameIn) const { - // Write Amber coordinate format - CpptrajFile cOut; - FileName fname(fnameIn); - if (cOut.OpenWrite(fname)) return; - cOut.Printf("%-80s\n", fname.base()); - int col = 0; - for (int ic = 0; ic != cframe_.size(); ic++) { - cOut.Printf("%8.3f", cframe_[ic]); - ++col; - if (col == 10) { - cOut.Printf("\n"); - col = 0; - } - } - if (col > 0) cOut.Printf("\n"); -} - -// ============================================================================= -/// Calculate smallest difference between two angles (in degrees). -static double DistCalc_Dih(double d1, double d2) { - double diff = fabs(d1 - d2); - if (diff > 180.0) - return (360.0 - diff); - else - return diff; -} - -/// Calculate basic difference. -static double DistCalc_Std(double d1, double d2) { - return fabs(d1 - d2); -} - -/* Update centroid value for adding/removing a frame. - * \param fval value of frame being added/removed. - * \param cval current centroid value. - * \param isTorsion data is periodic. - * \param oldSize Previous size of the centroid. - * \param OP Operation being performed. - */ -static double DistCalc_FrameCentroid(double fval, double cval, bool isTorsion, - double oldSize, ClusterDist::CentOpType OP, - double& sumx, double& sumy) -{ - double newcval; - if (isTorsion) { - double ftheta = fval * Constants::DEGRAD; - if (OP == ClusterDist::ADDFRAME) { - sumy += sin( ftheta ); - sumx += cos( ftheta ); - } else { // SUBTRACTFRAME - sumy -= sin( ftheta ); - sumx -= cos( ftheta ); - } - newcval = atan2(sumy, sumx) * Constants::RADDEG; - } else { - newcval = cval * oldSize; - if (OP == ClusterDist::ADDFRAME) { - newcval += fval; - newcval /= ( oldSize + 1 ); - } else { // SUBTRACTFRAME - newcval -= fval; - newcval /= ( oldSize - 1 ); - } - } - return newcval; -} - -// ----------------------------------------------------------------------------- -/** Calculate unambiguous average dihedral angle (in degrees) by converting to - * cartesian coords using x = cos(theta), y = sin(theta), and: - * tan(avgtheta) = avgy / avgx = SUM[sin(theta)] / SUM[cos(theta)] - * See Eq. 2 from Altis et al., J. Chem. Phys., 126 p. 244111 (2007). - */ -static double AvgCalc_Dih( DataSet_1D const& dsIn, ClusterDist::Cframes const& cframesIn, - double& sumx, double& sumy ) { - sumy = 0.0; - sumx = 0.0; - // TODO: Convert angles to radians prior to this call? - for (ClusterDist::Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) { - double theta = dsIn.Dval( *frm ) * Constants::DEGRAD; - sumy += sin( theta ); - sumx += cos( theta ); - } - return atan2(sumy, sumx) * Constants::RADDEG; -} - -static double AvgCalc_Std( DataSet_1D const& dsIn, ClusterDist::Cframes const& cframesIn ) { - double val = 0.0; - for (ClusterDist::Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) - val += dsIn.Dval( *frm ); - return (val / (double)cframesIn.size()); -} - -// ---------- Distance calc routines for single DataSet ------------------------ -ClusterDist_Num::ClusterDist_Num( DataSet* dsIn ) : - data_((DataSet_1D*)dsIn) -{ - if ( data_->Meta().IsTorsionArray() ) - dcalc_ = DistCalc_Dih; - else - dcalc_ = DistCalc_Std; -} - -double ClusterDist_Num::FrameDist(int f1, int f2) { - return dcalc_(data_->Dval(f1), data_->Dval(f2)); -} - -double ClusterDist_Num::CentroidDist(Centroid* c1, Centroid* c2) { - return dcalc_(((Centroid_Num*)c1)->cval_, ((Centroid_Num*)c2)->cval_); -} - -double ClusterDist_Num::FrameCentroidDist(int f1, Centroid* c1) { - return dcalc_(data_->Dval(f1), ((Centroid_Num*)c1)->cval_); -} - -/** Calculate avg value of given frames. */ -void ClusterDist_Num::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { - Centroid_Num* cent = (Centroid_Num*)centIn; - if (data_->Meta().IsTorsionArray()) - cent->cval_ = AvgCalc_Dih(*data_, cframesIn, cent->sumx_, cent->sumy_); - else - cent->cval_ = AvgCalc_Std(*data_, cframesIn); -} - -/** \return A new centroid of the given frames. */ -Centroid* ClusterDist_Num::NewCentroid( Cframes const& cframesIn ) { - Centroid_Num* cent = new Centroid_Num(); - CalculateCentroid( cent, cframesIn ); - return cent; -} - -void ClusterDist_Num::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, - CentOpType OP) -{ - Centroid_Num* cent = (Centroid_Num*)centIn; - cent->cval_ = DistCalc_FrameCentroid(data_->Dval(frame), cent->cval_, - data_->Meta().IsTorsionArray(), oldSize, OP, - cent->sumx_, cent->sumy_); -} - -std::string ClusterDist_Num::Description() const { - return "data " + data_->Meta().PrintName(); -} - -// ---------- Distance calc routines for multiple DataSets (Euclid) ------------ -ClusterDist_Euclid::ClusterDist_Euclid(DsArray const& dsIn) -{ - for (DsArray::const_iterator ds = dsIn.begin(); ds != dsIn.end(); ++ds) { - dsets_.push_back( (DataSet_1D*)*ds ); - if ( dsets_.back()->Meta().IsTorsionArray() ) - dcalcs_.push_back( DistCalc_Dih ); - else - dcalcs_.push_back( DistCalc_Std ); - } -} - -double ClusterDist_Euclid::FrameDist(int f1, int f2) { - double dist = 0.0; - DcArray::iterator dcalc = dcalcs_.begin(); - for (D1Array::iterator ds = dsets_.begin(); ds != dsets_.end(); ++ds, ++dcalc) { - double diff = (*dcalc)((*ds)->Dval(f1), (*ds)->Dval(f2)); - dist += (diff * diff); - } - return sqrt(dist); -} - -double ClusterDist_Euclid::CentroidDist(Centroid* c1, Centroid* c2) { - double dist = 0.0; - std::vector::iterator c2val = ((Centroid_Multi*)c2)->cvals_.begin(); - DcArray::iterator dcalc = dcalcs_.begin(); - for (std::vector::iterator c1val = ((Centroid_Multi*)c1)->cvals_.begin(); - c1val != ((Centroid_Multi*)c1)->cvals_.end(); - ++c1val, ++dcalc) - { - double diff = (*dcalc)(*c1val, *(c2val++)); - dist += (diff * diff); - } - return sqrt(dist); -} - -double ClusterDist_Euclid::FrameCentroidDist(int f1, Centroid* c1) { - double dist = 0.0; - std::vector::iterator c1val = ((Centroid_Multi*)c1)->cvals_.begin(); - DcArray::iterator dcalc = dcalcs_.begin(); - for (D1Array::iterator ds = dsets_.begin(); ds != dsets_.end(); ++ds) { - double diff = (*dcalc)((*ds)->Dval(f1), *(c1val++)); - dist += (diff * diff); - } - return sqrt(dist); -} - -void ClusterDist_Euclid::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { - Centroid_Multi* cent = (Centroid_Multi*)centIn; - cent->cvals_.resize( dsets_.size(), 0.0 ); - cent->Sumx_.resize( dsets_.size(), 0.0 ); - cent->Sumy_.resize( dsets_.size(), 0.0 ); - for (unsigned int idx = 0; idx != dsets_.size(); ++idx) { - if (dsets_[idx]->Meta().IsTorsionArray()) - cent->cvals_[idx] = AvgCalc_Dih(*dsets_[idx], cframesIn, cent->Sumx_[idx], cent->Sumy_[idx]); - else - cent->cvals_[idx] = AvgCalc_Std(*dsets_[idx], cframesIn); - } -// mprintf("DEBUG: Centroids:"); -// for (unsigned int i = 0; i != cent->cvals_.size(); i++) -// mprintf(" %f (sumy=%f sumx=%f)", cent->cvals_[i], cent->Sumy_[i], cent->Sumx_[i]); -// mprintf("\n"); -} - -Centroid* ClusterDist_Euclid::NewCentroid(Cframes const& cframesIn) { - Centroid_Multi* cent = new Centroid_Multi(); - CalculateCentroid(cent, cframesIn); - return cent; -} - -//static const char* OPSTRING[] = {"ADD", "SUBTRACT"}; // DEBUG - -void ClusterDist_Euclid::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, - CentOpType OP) -{ - Centroid_Multi* cent = (Centroid_Multi*)centIn; -// mprintf("DEBUG: Old Centroids:"); -// for (unsigned int i = 0; i != cent->cvals_.size(); i++) -// mprintf(" sumy=%f sumx=%f", cent->Sumy_[i], cent->Sumx_[i]); -// //mprintf(" %f", cent->cvals_[i]); -// mprintf("\n"); - for (unsigned int i = 0; i != dsets_.size(); ++i) - cent->cvals_[i] = DistCalc_FrameCentroid(dsets_[i]->Dval(frame), - cent->cvals_[i], dsets_[i]->Meta().IsTorsionArray(), oldSize, OP, - cent->Sumx_[i], cent->Sumy_[i]); -// mprintf("DEBUG: New Centroids after %s frame %i:", OPSTRING[OP], frame); -// for (unsigned int i = 0; i != cent->cvals_.size(); i++) -// mprintf(" %f", cent->cvals_[i]); -// mprintf("\n"); -} - -std::string ClusterDist_Euclid::Description() const { - std::string description("data "); - for (D1Array::const_iterator ds = dsets_.begin(); ds != dsets_.end(); ++ds) - if (ds == dsets_.begin()) - description.append( (*ds)->Meta().PrintName() ); - else - description.append( "," + (*ds)->Meta().PrintName() ); - return description; -} - -// ---------- Distance calc routines for COORDS DataSet using DME -------------- -ClusterDist_DME::ClusterDist_DME(DataSet* dIn, AtomMask const& maskIn) : - coords_((DataSet_Coords*)dIn), - mask_(maskIn) -{ - frm1_.SetupFrameFromMask(mask_, coords_->Top().Atoms()); - frm2_ = frm1_; -} - -double ClusterDist_DME::FrameDist(int f1, int f2) { - coords_->GetFrame( f1, frm1_, mask_ ); - coords_->GetFrame( f2, frm2_, mask_ ); - return frm1_.DISTRMSD( frm2_ ); -} - -double ClusterDist_DME::CentroidDist(Centroid* c1, Centroid* c2) { - return ((Centroid_Coord*)c1)->cframe_.DISTRMSD( ((Centroid_Coord*)c2)->cframe_ ); -} - -double ClusterDist_DME::FrameCentroidDist(int f1, Centroid* c1) { - coords_->GetFrame( f1, frm1_, mask_ ); - return frm1_.DISTRMSD( ((Centroid_Coord*)c1)->cframe_ ); -} - -/** Compute the centroid (avg) coords for each atom from all frames in this - * cluster. NOTE: For DME the centroid should probably be calculated via - * internal coordinates; use RMS best-fit as a cheat. - */ -void ClusterDist_DME::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { - Matrix_3x3 Rot; - Vec3 Trans; - Centroid_Coord* cent = (Centroid_Coord*)centIn; - // Reset atom count for centroid. - cent->cframe_.ClearAtoms(); - for (Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) - { - coords_->GetFrame( *frm, frm1_, mask_ ); - if (cent->cframe_.empty()) { - cent->cframe_ = frm1_; - cent->cframe_.CenterOnOrigin(false); - } else { - frm1_.RMSD_CenteredRef( cent->cframe_, Rot, Trans, false ); - frm1_.Rotate( Rot ); - cent->cframe_ += frm1_; - } - } - cent->cframe_.Divide( (double)cframesIn.size() ); - //mprintf("\t\tFirst 3 centroid coords (of %i): %f %f %f\n", cent->cframe_.Natom(), - // cent->cent->cframe_[0], cent->cframe_[1],cent->cframe_[2]); -} - -Centroid* ClusterDist_DME::NewCentroid( Cframes const& cframesIn ) { - // TODO: Incorporate mass? - Centroid_Coord* cent = new Centroid_Coord( mask_.Nselected() ); - CalculateCentroid( cent, cframesIn ); - return cent; -} - -void ClusterDist_DME::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, - CentOpType OP) -{ - Matrix_3x3 Rot; - Vec3 Trans; - Centroid_Coord* cent = (Centroid_Coord*)centIn; - coords_->GetFrame( frame, frm1_, mask_ ); - frm1_.RMSD_CenteredRef( cent->cframe_, Rot, Trans, false ); - frm1_.Rotate( Rot ); - cent->cframe_.Multiply( oldSize ); - if (OP == ADDFRAME) { - cent->cframe_ += frm1_; - cent->cframe_.Divide( oldSize + 1 ); - } else { // SUBTRACTFRAME - cent->cframe_ -= frm1_; - cent->cframe_.Divide( oldSize - 1 ); - } -} - -std::string ClusterDist_DME::Description() const { - return "dme " + mask_.MaskExpression(); -} - -// ---------- Distance calc routines for COORDS DataSets using RMSD ------------ -ClusterDist_RMS::ClusterDist_RMS(DataSet* dIn, AtomMask const& maskIn, - bool nofit, bool useMass) : - coords_((DataSet_Coords*)dIn), - mask_(maskIn), - nofit_(nofit), - useMass_(useMass) -{ - frm1_.SetupFrameFromMask(mask_, coords_->Top().Atoms()); - frm2_ = frm1_; -} - -double ClusterDist_RMS::FrameDist(int f1, int f2) { - coords_->GetFrame( f1, frm1_, mask_ ); - coords_->GetFrame( f2, frm2_, mask_ ); - if (nofit_) - return frm1_.RMSD_NoFit( frm2_, useMass_ ); - else - return frm1_.RMSD( frm2_, useMass_ ); -} - -double ClusterDist_RMS::CentroidDist(Centroid* c1, Centroid* c2) { - if (nofit_) - return ((Centroid_Coord*)c1)->cframe_.RMSD_NoFit( ((Centroid_Coord*)c2)->cframe_, useMass_ ); - else // Centroid is already at origin. - return ((Centroid_Coord*)c1)->cframe_.RMSD_CenteredRef( ((Centroid_Coord*)c2)->cframe_, - useMass_ ); -} - -double ClusterDist_RMS::FrameCentroidDist(int f1, Centroid* c1) { - coords_->GetFrame( f1, frm1_, mask_ ); - if (nofit_) - return frm1_.RMSD_NoFit( ((Centroid_Coord*)c1)->cframe_, useMass_ ); - else // Centroid is already at origin. - return frm1_.RMSD_CenteredRef( ((Centroid_Coord*)c1)->cframe_, useMass_ ); -} - -/** Compute the centroid (avg) coords for each atom from all frames in this - * cluster. If fitting, RMS fit to centroid as it is being built. - */ -void ClusterDist_RMS::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { - Matrix_3x3 Rot; - Vec3 Trans; - Centroid_Coord* cent = (Centroid_Coord*)centIn; - // Reset atom count for centroid. - cent->cframe_.ClearAtoms(); - for (Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) - { - coords_->GetFrame( *frm, frm1_, mask_ ); - if (cent->cframe_.empty()) { - cent->cframe_ = frm1_; - if (!nofit_) - cent->cframe_.CenterOnOrigin(useMass_); - } else { - if (!nofit_) { - frm1_.RMSD_CenteredRef( cent->cframe_, Rot, Trans, useMass_ ); - frm1_.Rotate( Rot ); - } - cent->cframe_ += frm1_; - } - } - cent->cframe_.Divide( (double)cframesIn.size() ); - //mprintf("\t\tFirst 3 centroid coords (of %i): %f %f %f\n", cent->cframe_.Natom(), - // cent->cent->cframe_[0], cent->cframe_[1],cent->cframe_[2]); -} - -Centroid* ClusterDist_RMS::NewCentroid( Cframes const& cframesIn ) { - // TODO: Incorporate mass? - Centroid_Coord* cent = new Centroid_Coord( mask_.Nselected() ); - CalculateCentroid( cent, cframesIn ); - return cent; -} - -// Subtract Notes -// FIXME: Handle single frame -// FIXME: Check if frame is in cluster? -void ClusterDist_RMS::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, - CentOpType OP) -{ - Matrix_3x3 Rot; - Vec3 Trans; - Centroid_Coord* cent = (Centroid_Coord*)centIn; - coords_->GetFrame( frame, frm1_, mask_ ); - if (!nofit_) { - frm1_.RMSD_CenteredRef( cent->cframe_, Rot, Trans, useMass_ ); - frm1_.Rotate( Rot ); - } - cent->cframe_.Multiply( oldSize ); - if (OP == ADDFRAME) { - cent->cframe_ += frm1_; - cent->cframe_.Divide( oldSize + 1 ); - } else { // SUBTRACTFRAME - cent->cframe_ -= frm1_; - cent->cframe_.Divide( oldSize - 1 ); - } -} - -std::string ClusterDist_RMS::Description() const { - std::string description("rms " + mask_.MaskExpression()); - if (nofit_) description.append(" nofit"); - if (useMass_) description.append(" mass"); - return description; -} - -// ---------- Distance calc routines for COORDS DataSets using SRMSD ----------- -ClusterDist_SRMSD::ClusterDist_SRMSD(DataSet* dIn, AtomMask const& maskIn, - bool nofit, bool useMass, int debugIn) : - coords_((DataSet_Coords*)dIn), - mask_(maskIn), - SRMSD_(mask_, !nofit, useMass, coords_->Top(), debugIn) -{ - frm1_.SetupFrameFromMask(mask_, coords_->Top().Atoms()); - frm2_ = frm1_; -} - -double ClusterDist_SRMSD::FrameDist(int f1, int f2) { - coords_->GetFrame( f1, frm1_, mask_ ); - coords_->GetFrame( f2, frm2_, mask_ ); - return SRMSD_.SymmRMSD(frm1_, frm2_); -} - -double ClusterDist_SRMSD::CentroidDist(Centroid* c1, Centroid* c2) { - // Centroid is already at origin. - return SRMSD_.SymmRMSD_CenteredRef( ((Centroid_Coord*)c1)->cframe_, - ((Centroid_Coord*)c2)->cframe_ ); -} - -double ClusterDist_SRMSD::FrameCentroidDist(int f1, Centroid* c1) { - coords_->GetFrame( f1, frm1_, mask_ ); - // Centroid is already at origin. - return SRMSD_.SymmRMSD_CenteredRef( frm1_, ((Centroid_Coord*)c1)->cframe_ ); -} - -/** Compute the centroid (avg) coords for each atom from all frames in this - * cluster. If fitting, RMS fit to centroid as it is being built. - */ -void ClusterDist_SRMSD::CalculateCentroid(Centroid* centIn, Cframes const& cframesIn) { - Matrix_3x3 Rot; - Vec3 Trans; - Centroid_Coord* cent = (Centroid_Coord*)centIn; - // Reset atom count for centroid. - cent->cframe_.ClearAtoms(); - for (Cframes_it frm = cframesIn.begin(); frm != cframesIn.end(); ++frm) - { - coords_->GetFrame( *frm, frm1_, mask_ ); - if (cent->cframe_.empty()) { - cent->cframe_ = frm1_; - if (SRMSD_.Fit()) - cent->cframe_.CenterOnOrigin(SRMSD_.UseMass()); - } else { - SRMSD_.SymmRMSD_CenteredRef( frm1_, cent->cframe_ ); - // Remap atoms - frm2_.SetCoordinatesByMap( frm1_, SRMSD_.AMap() ); - if (SRMSD_.Fit()) { - frm2_.Translate( SRMSD_.TgtTrans() ); - frm2_.Rotate( SRMSD_.RotMatrix() ); - } - cent->cframe_ += frm2_; - } - } - cent->cframe_.Divide( (double)cframesIn.size() ); - //mprintf("\t\tFirst 3 centroid coords (of %i): %f %f %f\n", cent->cframe_.Natom(), - // cent->cent->cframe_[0], cent->cframe_[1],cent->cframe_[2]); -} - -Centroid* ClusterDist_SRMSD::NewCentroid( Cframes const& cframesIn ) { - // TODO: Incorporate mass? - Centroid_Coord* cent = new Centroid_Coord( mask_.Nselected() ); - CalculateCentroid( cent, cframesIn ); - return cent; -} - -void ClusterDist_SRMSD::FrameOpCentroid(int frame, Centroid* centIn, double oldSize, - CentOpType OP) -{ - Matrix_3x3 Rot; - Vec3 Trans; - Centroid_Coord* cent = (Centroid_Coord*)centIn; - coords_->GetFrame( frame, frm1_, mask_ ); - SRMSD_.SymmRMSD_CenteredRef( frm1_, cent->cframe_ ); - // Remap atoms - frm2_.SetCoordinatesByMap( frm1_, SRMSD_.AMap() ); - if (SRMSD_.Fit()) { - frm2_.Translate( SRMSD_.TgtTrans() ); - frm2_.Rotate( SRMSD_.RotMatrix() ); - } - cent->cframe_.Multiply( oldSize ); - if (OP == ADDFRAME) { - cent->cframe_ += frm2_; - cent->cframe_.Divide( oldSize + 1 ); - } else { // SUBTRACTFRAME - cent->cframe_ -= frm2_; - cent->cframe_.Divide( oldSize - 1 ); - } -} - -std::string ClusterDist_SRMSD::Description() const { - std::string description("srmsd " + mask_.MaskExpression()); - if (!SRMSD_.Fit()) description.append(" nofit"); - if (SRMSD_.UseMass()) description.append(" mass"); - return description; -} diff --git a/src/ClusterDist.h b/src/ClusterDist.h deleted file mode 100644 index 5f98311b0c..0000000000 --- a/src/ClusterDist.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef INC_CLUSTERDIST_H -#define INC_CLUSTERDIST_H -#include "SymmetricRmsdCalc.h" -#include "DataSet_Coords.h" -#include "DataSet_1D.h" -/// Abstract Base Class for Cluster centroid. -/** This class is a container for the cluster centroid type appropriate for - * the data being clustered. For COORDS DataSets this is a frame, for other - * DataSets this is just a number. Centroid classes must implement a Copy() - * function. - */ -class Centroid { - public: - virtual ~Centroid() {} - virtual Centroid* Copy() = 0; - // TODO: Should centroids remember number of frames that went into them? - // This would make it so FrameOpCentroid wouldnt require extra arg. - virtual void Print(std::string const&) const {} -}; -/// Cluster centroid for generic DataSet. -class Centroid_Num : public Centroid { - public: - Centroid_Num() : cval_(0.0), sumx_(0.0), sumy_(0.0) {} - Centroid_Num(double val, double x, double y) : cval_(val), sumx_(x), sumy_(y) {} - Centroid* Copy() { return (Centroid*)new Centroid_Num(cval_, sumx_, sumy_); } - friend class ClusterDist_Num; - private: - double cval_; - double sumx_; // For storing periodic average - double sumy_; // For storing periodic average -}; -/// Cluster centroid for multiple DataSets -class Centroid_Multi : public Centroid { - public: - typedef std::vector Darray; - Centroid_Multi() {} - Centroid_Multi(Darray const& val, Darray const& x, Darray const& y) : - cvals_(val), Sumx_(x), Sumy_(y) {} - Centroid* Copy() { return (Centroid*)new Centroid_Multi(cvals_, Sumx_, Sumy_); } - friend class ClusterDist_Euclid; - private: - Darray cvals_; - Darray Sumx_; // For storing periodic average - Darray Sumy_; // For storing periodic average -}; -/// Cluster Centroid for Coords DataSet. -class Centroid_Coord : public Centroid { - public: - Centroid_Coord() {} - Centroid_Coord(Frame const& frame) : cframe_(frame) {} - Centroid_Coord(int natom) : cframe_(natom) {} - Centroid* Copy() { return (Centroid*)new Centroid_Coord(cframe_); } - void Print(std::string const&) const; - friend class ClusterDist_DME; - friend class ClusterDist_RMS; - friend class ClusterDist_SRMSD; - private: - Frame cframe_; -}; -// ----------------------------------------------------------------------------- -/// Abstract Base Class for Cluster distance calc. -class ClusterDist { - public: - enum CentOpType { ADDFRAME=0, SUBTRACTFRAME }; - /// Used to pass in absolute frame numbers for centroid calculations. - typedef std::vector Cframes; - typedef Cframes::const_iterator Cframes_it; - typedef std::vector DsArray; - virtual ~ClusterDist() {} - /// \return distance between given frames. - virtual double FrameDist(int, int) = 0; - /// \return distance between given centroids. - virtual double CentroidDist( Centroid*, Centroid* ) = 0; - /// \return distance between given frame and centroid. - virtual double FrameCentroidDist(int, Centroid* ) = 0; - /// Calculate centroid from given frames. - virtual void CalculateCentroid(Centroid*, Cframes const&) = 0; - /// \return new centroid from given frames. - virtual Centroid* NewCentroid(Cframes const&) = 0; - /// \return copy of this ClusterDist - virtual ClusterDist* Copy() = 0; - /// Update centroid by performing given operation between given frame and centroid. - virtual void FrameOpCentroid(int, Centroid*, double, CentOpType) = 0; - /// \return string containing description of the distance metric - virtual std::string Description() const = 0; - protected: - typedef double (*DistCalc)(double,double); -}; -/// Cluster distance calc for generic DataSet -class ClusterDist_Num : public ClusterDist { - public: - ClusterDist_Num() : data_(0), dcalc_(0) {} - ClusterDist_Num(DataSet*); - double FrameDist(int, int); - double CentroidDist( Centroid*, Centroid* ); - double FrameCentroidDist(int, Centroid*); - void CalculateCentroid(Centroid*, Cframes const&); - Centroid* NewCentroid(Cframes const&); - void FrameOpCentroid(int, Centroid*, double, CentOpType); - ClusterDist* Copy() { return new ClusterDist_Num( *this ); } - std::string Description() const; - private: - DataSet_1D* data_; - DistCalc dcalc_; -}; -/// Cluster distance calc using Euclid distance -class ClusterDist_Euclid : public ClusterDist { - public: - ClusterDist_Euclid() {} - ClusterDist_Euclid(DsArray const&); - double FrameDist(int, int); - double CentroidDist( Centroid*, Centroid* ); - double FrameCentroidDist(int, Centroid*); - void CalculateCentroid(Centroid*, Cframes const&); - Centroid* NewCentroid(Cframes const&); - void FrameOpCentroid(int, Centroid*, double, CentOpType); - ClusterDist* Copy() { return new ClusterDist_Euclid( *this ); } - std::string Description() const; - private: - typedef std::vector D1Array; - D1Array dsets_; - typedef std::vector DcArray; - DcArray dcalcs_; -}; -/// DME cluster distance calc for Coords DataSet. -class ClusterDist_DME: public ClusterDist { - public: - ClusterDist_DME() : coords_(0) {} - ClusterDist_DME(DataSet*,AtomMask const&); - double FrameDist(int, int); - double CentroidDist( Centroid*, Centroid* ); - double FrameCentroidDist(int, Centroid*); - void CalculateCentroid(Centroid*, Cframes const&); - Centroid* NewCentroid(Cframes const&); - void FrameOpCentroid(int, Centroid*, double, CentOpType); - ClusterDist* Copy() { return new ClusterDist_DME( *this ); } - std::string Description() const; - private: - DataSet_Coords* coords_; - AtomMask mask_; - Frame frm1_; ///< Temporary storage for frames from coords - Frame frm2_; ///< Temporary storage for frames from coords -}; -/// RMS cluster distance calc for Coords DataSet. -class ClusterDist_RMS : public ClusterDist { - public: - ClusterDist_RMS() : coords_(0), nofit_(false), useMass_(false) {} - ClusterDist_RMS(DataSet*,AtomMask const&,bool,bool); - double FrameDist(int, int); - double CentroidDist( Centroid*, Centroid* ); - double FrameCentroidDist(int, Centroid*); - void CalculateCentroid(Centroid*, Cframes const&); - void FrameOpCentroid(int, Centroid*, double, CentOpType); - Centroid* NewCentroid(Cframes const&); - ClusterDist* Copy() { return new ClusterDist_RMS( *this ); } - std::string Description() const; - private: - DataSet_Coords* coords_; - AtomMask mask_; - bool nofit_; - bool useMass_; - Frame frm1_; - Frame frm2_; -}; -/// Symmetry-corrected RMS distance calc for Coords DataSet. -class ClusterDist_SRMSD : public ClusterDist { - public: - ClusterDist_SRMSD() {} - ClusterDist_SRMSD(DataSet*,AtomMask const&,bool,bool,int); - double FrameDist(int, int); - double CentroidDist( Centroid*, Centroid* ); - double FrameCentroidDist(int, Centroid*); - void CalculateCentroid(Centroid*, Cframes const&); - Centroid* NewCentroid(Cframes const&); - void FrameOpCentroid(int, Centroid*, double, CentOpType); - ClusterDist* Copy() { return new ClusterDist_SRMSD( * this ); } - std::string Description() const; - private: - DataSet_Coords* coords_; - AtomMask mask_; - SymmetricRmsdCalc SRMSD_; - Frame frm1_; - Frame frm2_; -}; -#endif diff --git a/src/ClusterList.cpp b/src/ClusterList.cpp deleted file mode 100644 index 3dd0eb6092..0000000000 --- a/src/ClusterList.cpp +++ /dev/null @@ -1,1107 +0,0 @@ -#include // DBL_MAX -#include // sqrt -#include -#include // sort -#include // Find best reps -#include "ClusterList.h" -#include "CpptrajStdio.h" -#include "Constants.h" // Pseudo-F -#include "ProgressBar.h" -#include "StringRoutines.h" -#ifdef _OPENMP -# include -#endif -#include "PDBfile.h" // For writing out pseudo-graph - -// XMGRACE colors -const char* ClusterList::XMGRACE_COLOR[] = { - "white", "black", "red", "green", "blue", "yellow", "brown", "grey", "violet", - "cyan", "magenta", "orange", "indigo", "maroon", "turquoise", "darkgreen" -}; - -static const char* MetricStringArray[] = { - "RMSD", "DME", "Symmetry-corrected RMSD", "Data Set(s)" -}; - -const char* ClusterList::MetricString(DistMetricType dm) { - return MetricStringArray[dm]; -} - -// CONSTRUCTOR -ClusterList::ClusterList() : debug_(0), Cdist_(0), frameDistances_(0) {} - -// DESTRUCTOR -ClusterList::~ClusterList() { - if (Cdist_ != 0) delete Cdist_; -} - -// ClusterList::SetDebug() -/** Set the debug level */ -void ClusterList::SetDebug(int debugIn) { - debug_ = debugIn; - if (debug_>0) mprintf("ClusterList debug set to %i\n",debug_); -} - -/** Calculate the distance between the given clusters based on centroids. - * Centroids MUST be up to date. - */ -double ClusterList::ClusterDistance(ClusterNode const& C1, ClusterNode const& C2) const { - if (C1.Cent() == 0 || C2.Cent() == 0) { - mprinterr("Internal Error: One or both centroids are null in ClusterDistance()\n"); - return 0.0; - } - return Cdist_->CentroidDist( C1.Cent(), C2.Cent() ); -} - -// ClusterList::Renumber() -/** Sort clusters by size and renumber starting from 0, where cluster 0 - * is the largest. Also updates cluster centroids and adds back sieved - * frames if necessary. Ensures cluster node frame lists are sorted. - */ -void ClusterList::Renumber(bool addSievedFrames) { - // Update cluster centroids in case they need to be used to restore sieved frames. - for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) { - node->SortFrameList(); - node->CalculateCentroid( Cdist_ ); - } - // Add back sieved frames - if (addSievedFrames) { - mprintf("\tRestoring sieved frames.\n"); - AddSievedFrames(); - // Re-sort cluster frame lists and re-calculate centroids including sieved frames. - for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) { - node->SortFrameList(); - node->CalculateCentroid( Cdist_ ); - } - } - // Sort clusters by population and renumber. - clusters_.sort( ); - int newNum = 0; - for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) - node->SetNum( newNum++ ); -} - -// ----------------------------------------------------------------------------- -/// Used to pair representative score with frame number. -typedef std::pair RepPair; -/// Used to hold pairs of representative scores to frames. -typedef std::multimap RepMap; -/// Save up to maxSize of the best (lowest) representative scores/frames. -void SaveBestRep(RepMap& reps, RepPair const& Dist_Num, unsigned int maxSize) -{ - if (reps.size() < maxSize) - reps.insert( Dist_Num ); - else { - RepMap::reverse_iterator end = reps.rbegin(); - if (Dist_Num.first < end->first) { - //mprintf("DEBUG: %i (%30.15E) lower than %i (%30.15E)\n", Dist_Num.second, Dist_Num.first, end->second, end->first); - reps.insert( Dist_Num ); - if (reps.size() > maxSize) { - RepMap::iterator it = reps.end(); - --it; - reps.erase( it ); - } - } - } -} - -/// Set given cluster node with best representative frames/scores in reps -void SetBestRepFrame(ClusterNode& node, RepMap const& reps) { - if (!reps.empty()) { - node.BestReps().clear(); - for (RepMap::const_iterator it = reps.begin(); it != reps.end(); ++it) { - node.BestReps().push_back( ClusterNode::RepPair(it->second, it->first) ); - } - } -} - -// ClusterList::FindBestRepFrames_CumulativeDist() -/** Find the frame in each cluster that is the best representative by - * having the lowest cumulative distance to every other point in the cluster. - */ -int ClusterList::FindBestRepFrames_CumulativeDist(int nToSave) { - int err = 0; - for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) { - //node->Cent()->Print("centroid." + integerToString(node->Num())); // DEBUG - //CpptrajFile tmp; // DEBUG - //tmp.OpenWrite("c"+integerToString(node->Num())+".bestRep.dat"); // DEBUG - // Handle special cases - if (node->Nframes() == 1) { - node->BestReps().clear(); - if (debug_ > 0) - mprintf("DEBUG: Only 1 frame, best rep: %i\n", node->ClusterFrame(0)); - // Only one frame. That is the best rep. - node->BestReps().push_back( ClusterNode::RepPair(node->ClusterFrame(0), 0.0) ); - } else if (node->Nframes() == 2) { - node->BestReps().clear(); - if (debug_ > 0) - mprintf("DEBUG: 2 frames %i and %i, using former as best rep.\n", node->ClusterFrame(0), node->ClusterFrame(1)); - // Two frames, distance from f1 to f2 same as f2 to f1. Take f1 by convention. - node->BestReps().push_back( ClusterNode::RepPair(node->ClusterFrame(0), - Frame_Distance(node->ClusterFrame(0), node->ClusterFrame(1))) ); - } else { - // Find cumulative distance of each frame to all other frames. - RepMap bestReps; - for (ClusterNode::frame_iterator f1 = node->beginframe(); - f1 != node->endframe(); ++f1) - { - double cdist = 0.0; - for (ClusterNode::frame_iterator f2 = node->beginframe(); f2 != node->endframe(); ++f2) - { - if (f1 != f2) - cdist += Frame_Distance(*f1, *f2); - } - SaveBestRep(bestReps, RepPair(cdist, *f1), nToSave); - //tmp.Printf("%i %g %g\n", *f1+1, cdist, Cdist_->FrameCentroidDist(*f1, node->Cent())); - } - //tmp.CloseFile(); - if (bestReps.empty()) { - mprinterr("Error: Could not determine represenative frame for cluster %i\n", - node->Num()); - err++; - } - SetBestRepFrame( *node, bestReps ); - // DEBUG - if (debug_ > 0) { - mprintf("DEBUG: Best reps:\n"); - for (RepMap::const_iterator it = bestReps.begin(); it != bestReps.end(); ++it) - mprintf("\t%i (%20.10E)\n", it->second, it->first); - } - } - } - return err; -} - -/** Find the frame in each cluster that is the best representative by - * having the lowest cumulative distance to every other point in the cluster, - * ignoring sieved frames. - */ -int ClusterList::FindBestRepFrames_NoSieve_CumulativeDist(int nToSave) { - if (FrameDistances().SieveValue() != 1) - mprintf("Warning: Ignoring sieved frames while looking for best representative.\n"); - int err = 0; - for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) { - RepMap bestReps; - for (ClusterNode::frame_iterator f1 = node->beginframe(); f1 != node->endframe(); ++f1) - { - if (!FrameDistances().FrameWasSieved( *f1 )) { - double cdist = 0.0; - for (ClusterNode::frame_iterator f2 = node->beginframe(); f2 != node->endframe(); ++f2) - { - if (f1 != f2 && !FrameDistances().FrameWasSieved( *f2 )) - cdist += FrameDistances().GetFdist(*f1, *f2); - } - SaveBestRep(bestReps, RepPair(cdist, *f1), nToSave); - } - } - if (bestReps.empty()) { - mprinterr("Error: Could not determine represenative frame for cluster %i\n", - node->Num()); - err++; - } - SetBestRepFrame( *node, bestReps ); - } - return err; -} - -/** Find the frame in the cluster that is the best representative by - * having the lowest distance to the cluster centroid. - */ -int ClusterList::FindBestRepFrames_Centroid(int nToSave) { - int err = 0; - for (cluster_it node = clusters_.begin(); node != clusters_.end(); ++node) { - //mprintf("DEBUG: FindBestRepFrames_Centroid: Cluster %i\n", node->Num()); - RepMap bestReps; - //node->Cent()->Print("centroid." + integerToString(node->Num())); // DEBUG - for (ClusterNode::frame_iterator f1 = node->beginframe(); - f1 != node->endframe(); ++f1) - { - double dist = Cdist_->FrameCentroidDist(*f1, node->Cent()); - //mprintf("\t%8i %10.4g %10.4g %i\n", *f1+1, dist, mindist, minframe+1); - SaveBestRep(bestReps, RepPair(dist, *f1), nToSave); - } - if (bestReps.empty()) { - mprinterr("Error: Could not determine represenative frame for cluster %i\n", - node->Num()); - err++; - } - SetBestRepFrame( *node, bestReps ); - } - return err; -} - -// ----------------------------------------------------------------------------- -// ClusterList::DetermineNameWidth() -unsigned int ClusterList::DetermineNameWidth() const { - // Quick pass through clusters to determine width of cluster names - unsigned int nWidth = 0; - for (cluster_iterator node = begincluster(); node != endcluster(); ++node) - nWidth = std::max(nWidth, (unsigned int)node->Cname().size()); - return nWidth; -} - -// ClusterList::Summary() -/** Print a summary of clusters. */ -void ClusterList::Summary(std::string const& summaryfile, bool includeSieveInAvg) const -{ - CpptrajFile outfile; - double fmax = (double)FrameDistances().OriginalNframes(); - if (outfile.OpenWrite(summaryfile)) { - mprinterr("Error: ClusterList::Summary: Could not set up file.\n"); - return; - } - if (FrameDistances().SieveValue() != 1 && !includeSieveInAvg) - mprintf("Warning: Within cluster average distance (AvgDist) does not include sieved frames.\n"); - outfile.Printf("%-8s %8s %8s %8s %8s","#Cluster","Frames","Frac", - "AvgDist","Stdev"); - if (!clusters_.empty() && clusters_.front().BestReps().size() > 1) { - int nBestReps = clusters_.front().BestReps().size(); - for (int i = 0; i != nBestReps; i++) - outfile.Printf(" %8s %8s", "Rep", "RepScore"); - } else - outfile.Printf(" %8s", "Centroid"); - outfile.Printf(" %8s", "AvgCDist"); - unsigned int nWidth = DetermineNameWidth(); - if (nWidth > 0) { - if (nWidth < 8) nWidth = 8; - outfile.Printf(" %*s %8s", nWidth, "Name", "RMS"); - } - outfile.Printf("\n"); - //Timer t_fdist; // DEBUG - //Timer t_cdist; // DEBUG - //t_cdist.Start(); - // Calculate distances between clusters. - Matrix cluster_distances; - cluster_distances.resize( 0, clusters_.size() ); - for (cluster_iterator c1 = begincluster(); c1 != endcluster(); ++c1) - for (cluster_iterator c2 = c1; c2 != endcluster(); ++c2) - if (c2 != c1) - cluster_distances.addElement( ClusterDistance( *c1, *c2 ) ); - //t_cdist.Stop(); - - unsigned int idx1 = 0; - for (cluster_iterator node = begincluster(); node != endcluster(); ++node, ++idx1) - { - // Calculate the average distance of this cluster to every other cluster. - //t_cdist.Start(); - double avgclusterdist = 0.0; - if (clusters_.size() > 1) { - unsigned int idx2 = 0; - for (cluster_iterator node2 = begincluster(); node2 != endcluster(); ++node2, ++idx2) - { - if (node != node2) - avgclusterdist += cluster_distances.element(idx1, idx2); - } - avgclusterdist /= (double)(clusters_.size() - 1); - //mprintf("CLUSTER %i avgclusterdist= %g\n", node->Num(), avgclusterdist); - } - //t_cdist.Stop(); - // Since there may be a lot of frames do not calculate SD from the - // mean (which requires either storing distances or two double loops), - // instead use SD = sqrt( (SUM[x^2] - ((SUM[x])^2)/N)/N ) - //t_fdist.Start(); - double internalAvg = 0.0; - double internalSD = 0.0; - unsigned int Nelements = 0; - if (node->Nframes() > 1) { - // Calculate average distance between all frames in this cluster. - if (includeSieveInAvg) { - for (ClusterNode::frame_iterator f1 = node->beginframe(); f1 != node->endframe(); ++f1) { - for (ClusterNode::frame_iterator f2 = f1 + 1; f2 != node->endframe(); ++f2) { - double dist = Frame_Distance(*f1, *f2); - internalAvg += dist; - internalSD += (dist * dist); - ++Nelements; - } - } - } else { - for (ClusterNode::frame_iterator f1 = node->beginframe(); f1 != node->endframe(); ++f1) { - if (!FrameDistances().FrameWasSieved( *f1 )) { - for (ClusterNode::frame_iterator f2 = f1 + 1; f2 != node->endframe(); ++f2) { - if (!FrameDistances().FrameWasSieved( *f2 )) { - double dist = FrameDistances().GetFdist(*f1, *f2); - internalAvg += dist; - internalSD += (dist * dist); - ++Nelements; - } - } - } - } - } - if (Nelements > 0) { - double norm = 1.0 / ((double)Nelements); - internalAvg *= norm; - internalSD *= norm; - internalSD -= (internalAvg * internalAvg); - if (internalSD > 0.0) - internalSD = sqrt( internalSD ); - else - internalSD = 0.0; - } - //t_fdist.Stop(); - } - // OUTPUT - TODO handle case when clusters dont have same number best reps - outfile.Printf("%8i %8i %8.3f %8.3f %8.3f", - node->Num(), node->Nframes(), (double)node->Nframes()/fmax, - internalAvg, internalSD); - if (node->BestReps().size() < 2) - outfile.Printf(" %8i", node->BestRepFrame()+1); - else { - for (ClusterNode::RepPairArray::const_iterator rep = node->BestReps().begin(); - rep != node->BestReps().end(); ++rep) - outfile.Printf(" %8i %8.3f", rep->first+1, rep->second); - } - outfile.Printf(" %8.3f", avgclusterdist); - if (nWidth > 0) - outfile.Printf(" %*s %8.3f", nWidth, node->Cname().c_str(), node->RefRms()); - outfile.Printf("\n"); - } // END loop over clusters - //t_cdist.WriteTiming(1, "Between-cluster distance calc."); - //t_fdist.WriteTiming(1, "Within-cluster distance calc."); - outfile.CloseFile(); -} - -// ClusterList::Summary_Part -/** Print a summary of clustering for specified portions of the overall traj. - */ -void ClusterList::Summary_Part(std::string const& summaryfile, - std::vector const& splitFrames) const -{ - const char* nExt[] = {"st", "nd", "rd", "th"}; - if (splitFrames.empty()) return; // Sanity check. - CpptrajFile outfile; - double fmax = (double)FrameDistances().OriginalNframes(); - if (outfile.OpenWrite(summaryfile)) { - mprinterr("Error: Could not open file '%s'.\n", summaryfile.c_str()); - return; - } - - // Determine number of frames and traj offset for each part. - outfile.Printf("# 1st"); - std::vector partMax; - partMax.reserve( splitFrames.size() + 1 ); - std::vector trajOffset; - trajOffset.reserve( splitFrames.size() + 1); - trajOffset.push_back( 0 ); - int lastMax = 0; - unsigned int eidx = 1; - for (unsigned int sf = 0; sf < splitFrames.size(); sf++) - { - partMax.push_back( (double)(splitFrames[sf] - lastMax) ); - lastMax = splitFrames[sf]; - trajOffset.push_back( lastMax ); - outfile.Printf(" <= %i < %u%s", trajOffset.back(), sf+2, nExt[eidx]); - if (eidx < 3) ++eidx; - } - partMax.push_back( (double)(FrameDistances().OriginalNframes() - lastMax) ); - outfile.Printf("\n# "); - // Print # of frames in each section - eidx=0; - for (std::vector::const_iterator pm = partMax.begin(); pm != partMax.end(); ++pm) { - if (pm != partMax.begin()) outfile.Printf(" "); - outfile.Printf("%li%s= %.0f", pm - partMax.begin() + 1, nExt[eidx], *pm); - if (eidx < 3) ++eidx; - } - outfile.Printf("\n"); - // DEBUG - //mprintf("DEBUG: # Frames (offset):"); - //std::vector::const_iterator of = trajOffset.begin(); - //for (std::vector::const_iterator it = partMax.begin(); - // it != partMax.end(); ++it, ++of) - // mprintf(" %.0f (%i)", *it, *of); - //mprintf("\n"); - // Set up bins - std::vector numInPart( splitFrames.size() + 1, 0 ); - std::vector firstFrame( splitFrames.size() + 1, -1); - - // Header - outfile.Printf("#%-7s %8s %8s %2s %10s", "Cluster", "Total", "Frac", "C#", "Color"); - eidx = 0; - for (unsigned int pm = 1; pm <= partMax.size(); ++pm) { - outfile.Printf(" %5s%u%2s", "NumIn", pm, nExt[eidx]); - if (eidx < 3) ++eidx; - } - for (unsigned int pm = 1; pm <= partMax.size(); ++pm) - outfile.Printf(" %7s%u", "Frac", pm); - for (unsigned int pm = 1; pm <= partMax.size(); ++pm) - outfile.Printf(" %7s%u", "First", pm); - // Determine if cluster names will be output. - unsigned int nWidth = DetermineNameWidth(); - if (nWidth > 0) { - if (nWidth < 8) nWidth = 8; - outfile.Printf(" %*s %6s", nWidth, "Name", "RMS"); - } - outfile.Printf("\n"); - // LOOP OVER CLUSTERS - int color = 1; // xmgrace color, 1-15 - for (cluster_iterator node = begincluster(); node != endcluster(); ++node) - { - // Calculate size and fraction of total size of this cluster - int numframes = node->Nframes(); - double frac = (double)numframes / fmax; - std::fill( numInPart.begin(), numInPart.end(), 0 ); - std::fill( firstFrame.begin(), firstFrame.end(), -1 ); - // DEBUG - //mprintf("\tCluster %i\n",node->num); - // Count how many frames are in each part. - for (ClusterNode::frame_iterator frame1 = node->beginframe(); - frame1 != node->endframe(); - frame1++) - { - unsigned int bin = splitFrames.size(); - for (unsigned int sf = 0; sf < splitFrames.size(); ++sf) { - if ( *frame1 < splitFrames[sf] ) { - bin = sf; - break; - } - } - if (numInPart[ bin ] == 0) - firstFrame[ bin ] = *frame1 - trajOffset[ bin ] + 1; - ++numInPart[ bin ]; - } - outfile.Printf("%-8i %8i %8.4f %2i %10s", node->Num(), numframes, frac, - color, XMGRACE_COLOR[color]); - for (std::vector::const_iterator np = numInPart.begin(); - np != numInPart.end(); ++np) - outfile.Printf(" %8i", *np); - for (unsigned int pm = 0; pm < partMax.size(); ++pm) - outfile.Printf(" %8.4f", ((double)numInPart[pm]) / partMax[pm]); - for (std::vector::const_iterator ff = firstFrame.begin(); - ff != firstFrame.end(); ++ff) - outfile.Printf(" %8i", *ff); - if (nWidth > 0) - outfile.Printf(" %*s %6.2f", nWidth, node->Cname().c_str(), node->RefRms()); - outfile.Printf("\n"); - if (color<15) ++color; - } - outfile.CloseFile(); -} - -// ClusterList::PrintClustersToFile() -/** Print list of clusters in a style similar to ptraj; each cluster is - * given a line maxframes characters long, with X for each frame that is - * in the clusters and . for all other frames. Also print out the - * representative frame numbers. - */ -void ClusterList::PrintClustersToFile(std::string const& filename) const { - CpptrajFile outfile; - std::string buffer; - - if ( outfile.OpenWrite(filename) ) { - mprinterr("Error: PrintClustersToFile: Could not set up file %s\n", - filename.c_str()); - return; - } - outfile.Printf("#Clustering: %zu clusters %i frames\n", - clusters_.size(), FrameDistances().OriginalNframes()); - ComputeDBI( outfile ); - ComputePseudoF( outfile ); - // Call internal info routine. - ClusterResults( outfile ); - // Do not print trajectory stuff if no filename given (i.e. STDOUT output) - if (!filename.empty()) { - for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) - { - buffer.clear(); - buffer.resize(FrameDistances().OriginalNframes(), '.'); - for (ClusterNode::frame_iterator f1 = C1->beginframe(); f1 != C1->endframe(); ++f1) - buffer[ *f1 ] = 'X'; - buffer += '\n'; - outfile.Write((void*)buffer.c_str(), buffer.size()); - } - } - // Print representative frame numbers - outfile.Printf("#Representative frames:"); - for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) - if (C1->BestReps().size() < 2) - outfile.Printf(" %i", C1->BestRepFrame()+1); - else { - outfile.Printf(" {"); - for (ClusterNode::RepPairArray::const_iterator rep = C1->BestReps().begin(); - rep != C1->BestReps().end(); ++rep) - outfile.Printf(" %i %g", rep->first+1, rep->second); - outfile.Printf(" }"); - } - outfile.Printf("\n"); - // Print sieve info if present - if (FrameDistances().SieveValue() != 1) { - if (FrameDistances().SieveValue() < -1) { - outfile.Printf("#Sieve value: %i (random)\n#Sieved frames:", -FrameDistances().SieveValue()); - ClusterSieve::SievedFrames const& sFrames = FrameDistances().FramesToCluster(); - for (ClusterSieve::SievedFrames::const_iterator sfrm = sFrames.begin(); - sfrm != sFrames.end(); ++sfrm) - outfile.Printf(" %i", *sfrm + 1); - outfile.Printf("\n"); - } else - outfile.Printf("#Sieve value: %i\n", FrameDistances().SieveValue()); - } - outfile.CloseFile(); -} - -// ClusterList::PrintClusters() -/** Print list of clusters and frame numbers belonging to each cluster. - */ -void ClusterList::PrintClusters() const { - mprintf("CLUSTER: %zu clusters, %u frames.\n", clusters_.size(), - FrameDistances().OriginalNframes() ); - for (cluster_iterator C = begincluster(); C != endcluster(); C++) { - mprintf("\t%8i : ",C->Num()); - for (ClusterNode::frame_iterator fnum = C->beginframe(); - fnum != C->endframe(); ++fnum) - mprintf("%i,",(*fnum)+1); - mprintf("\n"); - } -} - -// ----------------------------------------------------------------------------- -// ClusterList::AddCluster() -/** Add a cluster made up of frames specified by the given list of frames to - * the cluster list. Cluster # is current cluster list size. - */ -int ClusterList::AddCluster( ClusterDist::Cframes const& framelistIn ) { - clusters_.push_back( ClusterNode( Cdist_, framelistIn, clusters_.size() ) ); - return 0; -} - -/** Set up the cluster distance calculation for the given input data sets - * and distance metric type. - */ -int ClusterList::SetupCdist( ClusterDist::DsArray const& dataSets, - DistMetricType metric, bool nofit, bool useMass, - std::string const& maskexpr ) -{ - if (dataSets.empty()) { // SANITY CHECK - mprinterr("Internal Error: SetupCdist: No DataSets given.\n"); - return 1; - } - // Base everything off of the first DataSet - DataSet* dsIn = dataSets[0]; - // Set up internal cluster disance calculation - if (metric != DATA) { - if (dsIn->Group() != DataSet::COORDINATES ) { - mprinterr("Internal Error: Metric is COORDS base but data set is not.\n"); - return 1; - } - // Test that the mask expression is valid - AtomMask testMask( maskexpr ); - Topology const& dsTop = ((DataSet_Coords*)dsIn)->Top(); - if ( dsTop.SetupIntegerMask( testMask ) ) { - mprinterr("Error: Could not set up mask '%s' for topology %s\n", - maskexpr.c_str(), dsTop.c_str()); - return 1; - } - testMask.MaskInfo(); - if (testMask.None()) { - mprinterr("Error: No atoms elected for mask '%s'\n", testMask.MaskString()); - return 1; - } - switch (metric) { - case DME: Cdist_ = new ClusterDist_DME(dsIn, testMask); break; - case RMS: Cdist_ = new ClusterDist_RMS(dsIn, testMask, nofit, useMass); break; - case SRMSD: Cdist_ = new ClusterDist_SRMSD(dsIn, testMask, nofit, useMass, debug_); break; - default: return 1; // Sanity check - } - } else { // Metric is DATA - if (dataSets.size() == 1) - Cdist_ = new ClusterDist_Num(dsIn); - else // TODO: More than just euclid - Cdist_ = new ClusterDist_Euclid(dataSets); - } - if (debug_ > 0) mprintf("DEBUG: ClusterDist= %s\n", Cdist_->Description().c_str()); - return 0; -} - -// ClusterList::CalcFrameDistances() -/** Set the frame pairwise distance matrix from the given data set and - * calculate it if need be. - */ -int ClusterList::CalcFrameDistances(DataSet* pwDistMatrixIn, - ClusterDist::DsArray const& dataSets, - int sieve, int sieveSeed) -{ - if (dataSets.empty()) { // SANITY CHECK - mprinterr("Internal Error: CalcFrameDistances: No DataSets given.\n"); - return 1; - } - if (Cdist_ == 0) { // SANITY CHECK - mprinterr("Internal Error: ClusterDist for given metric not yet allocated.\n"); - return 1; - } - frameDistances_ = (DataSet_Cmatrix*)pwDistMatrixIn; - if ( FrameDistances().NeedsSetup() ) { - // Set up cluster matrix with sieving info. Base total number - // of frames on first DataSet size. - if (frameDistances_->SetupWithSieve( Cdist_, dataSets[0]->Size(), sieve, sieveSeed )) - return 1; - // If cluster matrix needs calculation (i.e. not NOMEM), perform it. - if (FrameDistances().NeedsCalc()) { - mprintf("\tCalculating pair-wise distances.\n"); - ClusterSieve::SievedFrames const& frames = FrameDistances().FramesToCluster(); - int f2end = (int)frames.size(); - int f1end = f2end - 1; - ParallelProgress progress(f1end); - int f1, f2; - // For OMP, every other thread will need its own Cdist. - ClusterDist* MyCdist = Cdist_; -# ifdef _OPENMP -# pragma omp parallel private(MyCdist, f1, f2) firstprivate(progress) - { - int mythread = omp_get_thread_num(); - progress.SetThread( mythread ); - if (mythread == 0) { - mprintf("\tParallelizing pairwise distance calc with %i threads\n", omp_get_num_threads()); - MyCdist = Cdist_; - } else - MyCdist = Cdist_->Copy(); -# pragma omp for schedule(dynamic) -# endif - for (f1 = 0; f1 < f1end; f1++) { - progress.Update(f1); - for (f2 = f1 + 1; f2 < f2end; f2++) - frameDistances_->SetElement( f1, f2, MyCdist->FrameDist(frames[f1], frames[f2]) ); - } -# ifdef _OPENMP - if (mythread > 0) - delete MyCdist; - } // END omp parallel -# endif - progress.Finish(); - } - // Currently this is only for DataSet_Cmatrix_DISK - frameDistances_->Complete(); - } else - // Pairwise distance matrix already set up - mprintf("\tUsing existing pairwise distances from '%s'\n", FrameDistances().legend()); - mprintf("\tMemory used by pair-wise matrix and other cluster data: %s\n", - ByteString(FrameDistances().DataSize(), BYTE_DECIMAL).c_str()); - // DEBUG - Print Frame distances - if (debug_ > 1) { - mprintf("INITIAL FRAME DISTANCES:\n"); - FrameDistances().PrintElements(); - } - return 0; -} - -// ClusterList::RemoveEmptyClusters() -void ClusterList::RemoveEmptyClusters() { - cluster_it cnode = clusters_.begin(); - while (cnode != clusters_.end()) { - if (cnode->Nframes() == 0) - cnode = clusters_.erase( cnode ); - else - ++cnode; - } -} - -// ----------------------------------------------------------------------------- -void ClusterList::AddSievedFramesByCentroid() { - // NOTE: All cluster centroids must be up to date. - int frame; - int nframes = (int)FrameDistances().OriginalNframes(); - double mindist, dist; - cluster_it minNode, Cnode; - ParallelProgress progress( nframes ); - // For OMP, every other thread will need its own Cdist. - ClusterDist* MyCdist = Cdist_; -# ifdef _OPENMP - // For OMP need a temp. array to hold which frame goes to which cluster to avoid clashes - std::vector frameToCluster( nframes, clusters_.end() ); -# pragma omp parallel private(MyCdist, frame, dist, mindist, minNode, Cnode) firstprivate(progress) - { - int mythread = omp_get_thread_num(); - progress.SetThread( mythread ); - if (mythread == 0) { - mprintf("\tParallelizing sieve restore calc with %i threads\n", omp_get_num_threads()); - MyCdist = Cdist_; - } else - MyCdist = Cdist_->Copy(); -# pragma omp for schedule(dynamic) -# endif - for (frame = 0; frame < nframes; ++frame) { - progress.Update( frame ); - if (FrameDistances().FrameWasSieved(frame)) { - // Which clusters centroid is closest to this frame? - mindist = DBL_MAX; - minNode = clusters_.end(); - for (Cnode = clusters_.begin(); Cnode != clusters_.end(); ++Cnode) { - dist = MyCdist->FrameCentroidDist(frame, Cnode->Cent()); - if (dist < mindist) { - mindist = dist; - minNode = Cnode; - } - } - // Add sieved frame to the closest cluster. -# ifdef _OPENMP - frameToCluster[frame] = minNode; -# else - minNode->AddFrameToCluster( frame ); -# endif - } - } // END loop over frames -# ifdef _OPENMP - if (mythread > 0) - delete MyCdist; - } // END pragma omp parallel - // Now actually add sieved frames to their appropriate clusters - for (frame = 0; frame < nframes; frame++) - if (frameToCluster[frame] != clusters_.end()) - (*frameToCluster[frame]).AddFrameToCluster( frame ); -# endif - progress.Finish(); -} - -// ----------------------------------------------------------------------------- -/** The Davies-Bouldin Index (DBI) measures the average similarity between each - * cluster and its most similar one; the smaller the DBI, the better. The DBI - * is defined as the average, for all clusters X, of fred, where fred(X) = max, - * across other clusters Y, of (Cx + Cy)/dXY. Here Cx is the average distance - * from points in X to the centroid, similarly Cy, and dXY is the distance - * between cluster centroids. - * NOTE: To use this, cluster centroids should be fully up-to-date. - */ -double ClusterList::ComputeDBI(CpptrajFile& outfile) const { - std::vector averageDist; - averageDist.reserve( clusters_.size() ); - for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) { - // Calculate average distance to centroid for this cluster - averageDist.push_back( C1->CalcAvgToCentroid( Cdist_ ) ); - if (outfile.IsOpen()) - outfile.Printf("#Cluster %i has average-distance-to-centroid %f\n", - C1->Num(), averageDist.back()); - } - double DBITotal = 0.0; - unsigned int nc1 = 0; - for (cluster_iterator c1 = begincluster(); c1 != endcluster(); ++c1, ++nc1) { - double MaxFred = 0; - unsigned int nc2 = 0; - for (cluster_iterator c2 = begincluster(); c2 != endcluster(); ++c2, ++nc2) { - if (c1 != c2) { - double Fred = averageDist[nc1] + averageDist[nc2]; - Fred /= Cdist_->CentroidDist( c1->Cent(), c2->Cent() ); - if (Fred > MaxFred) - MaxFred = Fred; - } - } - DBITotal += MaxFred; - } - DBITotal /= (double)clusters_.size(); - if (outfile.IsOpen()) outfile.Printf("#DBI: %f\n", DBITotal); - return DBITotal; -} - -/** The pseudo-F statistic is another measure of clustering goodness. It is - * intended to capture the 'tightness' of clusters, and is in essence a ratio - * of the mean sum of squares between groups to the mean sum of squares within - * group (Lattin et al., 2003: 291) High values are good. Generally, one - * selects a cluster-count that gives a peak in the pseudo-f statistic (or - * pSF, for short). - * Formula: A/B, where A = (T - P)/(G-1), and B = P / (n-G). Here n is the - * number of points, G is the number of clusters, T is the total distance from - * the all-data centroid, and P is the sum (for all clusters) of the distances - * from the cluster centroid. - * NOTE: To use this, cluster centroids should be fully up-to-date. - * NOTE: This calc differs slightly from PTRAJ in that real centroids are used - * instead of representative structures. - */ -double ClusterList::ComputePseudoF(CpptrajFile& outfile) const { - // Calculation makes no sense with fewer than 2 clusters. - if (Nclusters() < 2) { - mprintf("Warning: Fewer than 2 clusters. Not calculating pseudo-F.\n"); - return 0.0; - } - - // Form a cluster with all points to get a centroid. Use only frames that - // are in clusters, i.e. ignore noise. Assumes all cluster centroids are - // up to date. - ClusterNode c_all; - for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) - { - for (ClusterNode::frame_iterator f1 = C1->beginframe(); f1 != C1->endframe(); ++f1) - c_all.AddFrameToCluster( *f1 ); - } - // Pseudo-F makes no sense if # clusters == # frames - if (Nclusters() == c_all.Nframes()) { - mprintf("Warning: Each frame is in a separate cluster. Not calculating pseudo-F.\n"); - return 0.0; - } - c_all.SortFrameList(); - c_all.CalculateCentroid( Cdist_ ); - - // Loop over all clusters - double gss = 0.0; // between-group sum of squares - double wss = 0.0; // within-group sum of squares - for (cluster_iterator C1 = begincluster(); C1 != endcluster(); ++C1) - { - for (ClusterNode::frame_iterator f1 = C1->beginframe(); f1 != C1->endframe(); ++f1) - { - double dist = Cdist_->FrameCentroidDist(*f1, c_all.Cent()); - gss += (dist * dist); - dist = Cdist_->FrameCentroidDist(*f1, C1->Cent()); - wss += (dist * dist); - } - } - double d_nclusters = (double)Nclusters(); - double d_ntotal = (double)c_all.Nframes(); - double num = (gss - wss) / (d_nclusters - 1.0); - double den = wss / (d_ntotal - d_nclusters); - if (den < Constants::SMALL) - den = Constants::SMALL; - double pseudof = num / den; - if (debug_ > 0) - mprintf("Pseudo-f: Total distance to centroid is %.4f\n" - "Pseudo-f: Cluster distance to centroid is %.4f\n" - "Pseudo-f: Numerator %.4f over denominator %.4f gives %.4f\n", - gss, wss, num, den, pseudof); - if (outfile.IsOpen()) { - outfile.Printf("#pSF: %f\n", pseudof); - // This calculation taken directly from ptraj - double SSRSST = pseudof*(d_nclusters-1)/(d_ntotal-d_nclusters+pseudof*(d_nclusters-1)); - outfile.Printf("#SSR/SST: %f\n", SSRSST); - } - - return pseudof; -} - -/** The cluster silhouette is a measure of how well each point fits within - * a cluster. Values of 1 indicate the point is very similar to other points - * in the cluster, i.e. it is well-clustered. Values of -1 indicate the point - * is dissimilar and may fit better in a neighboring cluster. Values of 0 - * indicate the point is on a border between two clusters. - */ -void ClusterList::CalcSilhouette(std::string const& prefix, bool includeSieved) const { - mprintf("\tCalculating cluster/frame silhouette.\n"); - if (FrameDistances().SieveValue() != 1 && !includeSieved) - mprintf("Warning: Silhouettes do not include sieved frames.\n"); - CpptrajFile Ffile, Cfile; - if (Ffile.OpenWrite(prefix + ".frame.dat")) return; - if (Cfile.OpenWrite(prefix + ".cluster.dat")) return; - Cfile.Printf("%-8s %10s\n", "#Cluster", ""); - unsigned int idx = 0; - for (cluster_iterator Ci = begincluster(); Ci != endcluster(); ++Ci) - { - Ffile.Printf("#C%-6i %10s\n", Ci->Num(), "Silhouette"); - double avg_si = 0.0; - int ci_frames = 0; - std::vector SiVals; - for (ClusterNode::frame_iterator f1 = Ci->beginframe(); f1 != Ci->endframe(); ++f1) - { - if (includeSieved || !FrameDistances().FrameWasSieved( *f1 )) { - // Calculate the average dissimilarity of this frame with all other - // points in this frames cluster. - double ai = 0.0; - int self_frames = 0; - if (includeSieved) { - for (ClusterNode::frame_iterator f2 = Ci->beginframe(); f2 != Ci->endframe(); ++f2) - { - if (f1 != f2) { - ai += Frame_Distance(*f1, *f2); - ++self_frames; - } - } - } else { - for (ClusterNode::frame_iterator f2 = Ci->beginframe(); f2 != Ci->endframe(); ++f2) - { - if (f1 != f2 && !FrameDistances().FrameWasSieved(*f2)) { - ai += FrameDistances().GetFdist(*f1, *f2); - ++self_frames; - } - } - } - if (self_frames > 0) - ai /= (double)self_frames; - //mprintf("\t\tFrame %i cluster %i ai = %g\n", *f1+1, Ci->Num(), ai); - // Determine lowest average dissimilarity of this frame with all - // other clusters. - double min_bi = DBL_MAX; - for (cluster_iterator Cj = begincluster(); Cj != endcluster(); ++Cj) - { - if (Ci != Cj) - { - double bi = 0.0; - // NOTE: ASSUMING NO EMPTY CLUSTERS - if (includeSieved) { - for (ClusterNode::frame_iterator f2 = Cj->beginframe(); f2 != Cj->endframe(); ++f2) - bi += Frame_Distance(*f1, *f2); - bi /= (double)Cj->Nframes(); - } else { - int cj_frames = 0; - for (ClusterNode::frame_iterator f2 = Cj->beginframe(); f2 != Cj->endframe(); ++f2) - { - if (!FrameDistances().FrameWasSieved(*f2)) { - bi += FrameDistances().GetFdist(*f1, *f2); - ++cj_frames; - } - } - bi /= (double)cj_frames; - } - //mprintf("\t\tFrame %i to cluster %i bi = %g\n", *f1 + 1, Cj->Num(), bi); - if (bi < min_bi) - min_bi = bi; - } - } - double max_ai_bi = std::max( ai, min_bi ); - if (max_ai_bi == 0.0) - mprinterr("Error: Divide by zero in silhouette calculation for frame %i\n", *f1 + 1); - else { - double si = (min_bi - ai) / max_ai_bi; - SiVals.push_back( si ); - //Ffile.Printf("%8i %10.4f\n", *f1 + 1, si); - avg_si += si; - ++ci_frames; - } - } - } // END loop over cluster frames - std::sort( SiVals.begin(), SiVals.end() ); - for (std::vector::const_iterator it = SiVals.begin(); it != SiVals.end(); ++it, ++idx) - Ffile.Printf("%8i %g\n", idx, *it); - Ffile.Printf("\n"); - ++idx; - if (ci_frames > 0) - avg_si /= (double)ci_frames; - Cfile.Printf("%8i %g\n", Ci->Num(), avg_si); - } -} - -// ----------------------------------------------------------------------------- -void ClusterList::DrawGraph(bool use_z, DataSet* cnumvtime, - double min_tol, int max_iteration) const -{ - if (use_z) - mprintf("\tCreating PDB of graph points based on pairwise distances. B-factor = cluster #.\n"); - else - mprintf("\tAttempting to draw graph based on pairwise distances.\n"); - unsigned int nframes = FrameDistances().Nrows(); - std::vector Xarray; // Coords - std::vector Farray; // Forces - Xarray.reserve( nframes ); - Farray.assign( nframes, Vec3(0.0) ); - // Initialize coordinates. X and Y only. - double zcoord = 0.0; - double theta_deg = 0.0; - double delta = 360.0 / (double)nframes; - for (unsigned int n = 0; n != nframes; n++, theta_deg += delta) { - double theta_rad = Constants::DEGRAD * theta_deg; - if (use_z) - zcoord = cos(theta_rad / 2.0); - Xarray.push_back( Vec3(cos(theta_rad), sin(theta_rad), zcoord) ); - } - // Write out initial graph - if (debug_ > 0 && !use_z) { - CpptrajFile graph0; - if (graph0.OpenWrite("InitialGraph.dat")) return; - for (std::vector::const_iterator XV = Xarray.begin(); - XV != Xarray.end(); ++XV) - graph0.Printf("%g %g %li\n", (*XV)[0], (*XV)[1], XV - Xarray.begin() + 1); - graph0.CloseFile(); - } - // Degrees of freedom. If Z ever initialized needs to be 3N - double deg_of_freedom = 2.0 * (double)nframes; - if (use_z) deg_of_freedom += (double)nframes; - double fnq = sqrt( deg_of_freedom ); - // Main loop for steepest descent - const double Rk = 1.0; - const double dxstm = 1.0E-5; - const double crits = 1.0E-6; - double rms = 1.0; - double dxst = 0.1; - double last_e = 0.0; - int iteration = 0; - mprintf(" \t%8s %12s %12s\n", " ", "ENE", "RMS"); - while (rms > min_tol && iteration < max_iteration) { - double e_total = 0.0; - unsigned int idx = 0; // Index into FrameDistances - for (unsigned int f1 = 0; f1 != nframes; f1++) - { - for (unsigned int f2 = f1 + 1; f2 != nframes; f2++) - { - //double Req = FrameDistances().GetCdist(f1, f2); - Vec3 V1_2 = Xarray[f1] - Xarray[f2]; - double r2 = V1_2.Magnitude2(); - double s = sqrt(r2); - double r = 2.0 / s; - double db = s - FrameDistances().GetElement(idx++); - double df = Rk * db; - double e = df * db; - e_total += e; - df *= r; - // Apply force - V1_2 *= df; - Farray[f1] -= V1_2; - Farray[f2] += V1_2; - } - } - // Calculate the magnitude of the force vector. - double sum = 0.0; - for (std::vector::const_iterator FV = Farray.begin(); FV != Farray.end(); ++FV) - sum += FV->Magnitude2(); - rms = sqrt( sum ) / fnq; - // Adjust search step size - if (dxst < crits) dxst = dxstm; - dxst = dxst / 2.0; - if (e_total < last_e) dxst = dxst * 2.4; - double dxsth = dxst / sqrt( sum ); - last_e = e_total; - // Update positions and reset force array. - std::vector::iterator FV = Farray.begin(); - for (std::vector::iterator XV = Xarray.begin(); - XV != Xarray.end(); ++XV, ++FV) - { - *XV += (*FV * dxsth); - *FV = 0.0; - } - // Write out current E. - mprintf("Iteration:\t%8i %12.4E %12.4E\n", iteration, e_total, rms); - iteration++; - } - // RMS error - unsigned int idx = 0; // Index into FrameDistances - double sumdiff2 = 0.0; - for (unsigned int f1 = 0; f1 != nframes; f1++) - { - for (unsigned int f2 = f1 + 1; f2 != nframes; f2++) - { - Vec3 V1_2 = Xarray[f1] - Xarray[f2]; - double r1_2 = sqrt( V1_2.Magnitude2() ); - double Req = FrameDistances().GetElement(idx); - double diff = r1_2 - Req; - sumdiff2 += (diff * diff); - if (debug_ > 0) - mprintf("\t\t%u to %u: D= %g Eq= %g Delta= %g\n", - f1+1, f2+1, r1_2, Req, fabs(diff)); - ++idx; - } - } - double rms_err = sqrt( sumdiff2 / (double)FrameDistances().Nelements() ); - mprintf("\tRMS error of final graph positions: %g\n", rms_err); - // Write out final graph with cluster numbers. - std::vector Nums; - Nums.reserve( nframes ); - if (cnumvtime != 0) { - ClusterSieve::SievedFrames const& sievedFrames = FrameDistances().FramesToCluster(); - DataSet_1D const& CVT = static_cast( *cnumvtime ); - for (unsigned int n = 0; n != nframes; n++) - Nums.push_back( (int)CVT.Dval(sievedFrames[n]) ); - } else - for (int n = 1; n <= (int)nframes; n++) - Nums.push_back( n ); - if (!use_z) { - CpptrajFile graph; - if (graph.OpenWrite("DrawGraph.dat")) return; - for (std::vector::const_iterator XV = Xarray.begin(); - XV != Xarray.end(); ++XV) - graph.Printf("%g %g %i \"%li\"\n", (*XV)[0], (*XV)[1], - Nums[XV - Xarray.begin()], XV - Xarray.begin() + 1); - graph.CloseFile(); - } else { - // Write out PDB with B-factors - PDBfile pdbout; - if (pdbout.OpenWrite("DrawGraph.pdb")) return; - pdbout.WriteTITLE("Cluster points."); - for (std::vector::const_iterator XV = Xarray.begin(); - XV != Xarray.end(); ++XV) - pdbout.WriteCoord(PDBfile::HETATM, XV - Xarray.begin() + 1, "HE", "HE", - XV - Xarray.begin() + 1, (*XV)[0], (*XV)[1], (*XV)[2], - 1.0, Nums[XV - Xarray.begin()], "HE", 0); - pdbout.CloseFile(); - } -} diff --git a/src/ClusterList.h b/src/ClusterList.h deleted file mode 100644 index 3e136a4eb2..0000000000 --- a/src/ClusterList.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef INC_CLUSTERLIST_H -#define INC_CLUSTERLIST_H -#include -#include "ArgList.h" -#include "ClusterNode.h" -// Class: ClusterList -/** This base class holds all the individual clusters, as well as routines - * that can be used to obtain information on clusters after clustering. - */ -// TODO Create ClusterFrameDistance class to hold combined DataSet_Cmatrix and ClusterDist -class ClusterList { - public: - enum DistMetricType { RMS = 0, DME, SRMSD, DATA }; - static const char* MetricString( DistMetricType ); - ClusterList(); - virtual ~ClusterList(); - int Nclusters() const { return (int)clusters_.size(); } - - void SetDebug(int); - /// Add back sieved frames, update centroids, sort by cluster population. - void Renumber(bool); - /// Determine which frame in each cluster is best representative using cumulative distance. - int FindBestRepFrames_CumulativeDist(int); - /// Determine which frame (ignoring sieved) in each cluster is best representative. - int FindBestRepFrames_NoSieve_CumulativeDist(int); - /// Determine which frame in each cluster is best representative by distance to centroid. - int FindBestRepFrames_Centroid(int); - /// Print overall summary of clusters. - void Summary(std::string const&,bool) const; - /// Print summary of clusters separated by parts. - void Summary_Part(std::string const&,std::vector const&) const; - /// Print cluster info. - void PrintClustersToFile(std::string const&) const; - /// DEBUG: Print clusters to STDOUT - void PrintClusters() const; - /// Set up appropriate cluster distance calculation - int SetupCdist( ClusterDist::DsArray const&, DistMetricType, bool, bool, std::string const&); - /// Calculate distances between frames if necessary. - int CalcFrameDistances(DataSet*, ClusterDist::DsArray const&, int, int); - // ----- Inherited by individual clustering methods ---- - /// Process algorithm-specific keywords - virtual int SetupCluster(ArgList&) = 0; - /// Print summary of clustering to be performed - virtual void ClusteringInfo() const = 0; - /// Perform clustering. - virtual int Cluster() = 0; - /// \return distance between given clusters. Default is distance between centroids. - virtual double ClusterDistance(ClusterNode const&, ClusterNode const&) const; -# ifdef TIMER - virtual void Timing(double) const = 0; -# endif - /// Iterator over clusters - typedef std::list::iterator cluster_it; - cluster_it begin() { return clusters_.begin(); } - cluster_it end() { return clusters_.end(); } - /// Const Iterator over clusters - typedef std::list::const_iterator cluster_iterator; - const cluster_iterator begincluster() const { return clusters_.begin(); } - const cluster_iterator endcluster() const { return clusters_.end(); } - /// Remove clusters with no members. - void RemoveEmptyClusters(); - /// Calculate cluster silhouettes - void CalcSilhouette(std::string const&, bool) const; - - void DrawGraph(bool,DataSet*,double,int) const; - protected: - /// Restore sieved frames to clusters - virtual void AddSievedFrames() = 0; - virtual void ClusterResults(CpptrajFile&) const = 0; - - /// \return Distance between specified frames. Use FrameDistances if frames were not sieved. - inline double Frame_Distance(int,int) const; - /// Add each sieved frame to the nearest cluster based on frame to centroid distance. - void AddSievedFramesByCentroid(); - DataSet_Cmatrix const& FrameDistances() const { return *frameDistances_; } - int debug_; - /// Store individual cluster info; frame numbers, centroid, etc. - std::list clusters_; - /// Used to calculate distances between frames and/or centroids. - ClusterDist* Cdist_; - /// Add specified frames to a new cluster. - int AddCluster(ClusterDist::Cframes const&); - private: - static const char* XMGRACE_COLOR[]; - /// Determine max name width - unsigned int DetermineNameWidth() const; - /// Calculate the Davies-Bouldin index of clusters. Centroids must be up-to-date. - double ComputeDBI(CpptrajFile&) const; - /// Calculate pseudo-F statistic. - double ComputePseudoF(CpptrajFile&) const; - - /// Hold pointer to matrix containing distances between each frame. - DataSet_Cmatrix* frameDistances_; -}; -// ----- INLINE FUNCTIONS ------------------------------------------------------ -double ClusterList::Frame_Distance(int f1, int f2) const { - if (FrameDistances().FrameWasSieved(f1) || - FrameDistances().FrameWasSieved(f2)) - return Cdist_->FrameDist(f1, f2); - else - return FrameDistances().GetFdist(f1, f2); -} -#endif diff --git a/src/ClusterNode.cpp b/src/ClusterNode.cpp deleted file mode 100644 index 2e9e1a8960..0000000000 --- a/src/ClusterNode.cpp +++ /dev/null @@ -1,148 +0,0 @@ -//#incl ude // DBL_MAX -#include // sort -#include "ClusterNode.h" - -// CONSTRUCTOR -ClusterNode::ClusterNode() : - eccentricity_(0), - num_(0), - centroid_(0) -{} - -// DESTRUCTOR -ClusterNode::~ClusterNode() { - if (centroid_ != 0) delete centroid_; -} - -/** Create new cluster with given number containing given frames. Calculate - * initial centroid and set initial best rep frame to front, even though - * that will probably be wrong when number of frames in the list > 1. - */ -ClusterNode::ClusterNode(ClusterDist* Cdist, ClusterDist::Cframes const& frameListIn, int numIn) : - eccentricity_(0.0), - num_(numIn), - bestReps_(1, RepPair(frameListIn.front(), 0.0)), - frameList_(frameListIn), - centroid_(Cdist->NewCentroid(frameList_)) -{} - -// COPY CONSTRUCTOR -ClusterNode::ClusterNode(const ClusterNode& rhs) : - eccentricity_( rhs.eccentricity_ ), - num_( rhs.num_ ), - bestReps_( rhs.bestReps_ ), - frameList_( rhs.frameList_ ), - centroid_(0) -{ - if (rhs.centroid_ != 0) - centroid_ = rhs.centroid_->Copy(); -} - -// ASSIGNMENT -ClusterNode& ClusterNode::operator=(const ClusterNode& rhs) { - if (&rhs == this) return *this; - eccentricity_ = rhs.eccentricity_; - num_ = rhs.num_; - bestReps_ = rhs.bestReps_; - frameList_ = rhs.frameList_; - if (centroid_ != 0) delete centroid_; - if (rhs.centroid_ != 0) - centroid_ = rhs.centroid_->Copy(); - else - centroid_ = 0; - return *this; -} - -/** Find the frame in the given cluster that is the best representative via - * having the lowest cumulative distance to every other point in the cluster. - * Should NOT be used if cluster contains sieved frames. - * \return best representative frame number, or -1 on error. - */ -/* -int ClusterNode::SetBestRep_CumulativeDist(DataSet_Cmatrix const& FrameDistancesIn) { - double mindist = DBL_MAX; - int minframe = -1; - for (frame_iterator frm1 = frameList_.begin(); frm1 != frameList_.end(); ++frm1) - { - double cdist = 0.0; - for (frame_iterator frm2 = frameList_.begin(); frm2 != frameList_.end(); ++frm2) - { - if (frm1 != frm2) - cdist += FrameDistancesIn.GetFdist(*frm1, *frm2); - } - if (cdist < mindist) { - mindist = cdist; - minframe = *frm1; - } - } - if (minframe == -1) - return -1; - repFrame_ = minframe; - return minframe; -}*/ - -/** Calculate the eccentricity of this cluster (i.e. the largest distance - * between any two points in the cluster). - */ -void ClusterNode::CalcEccentricity(DataSet_Cmatrix const& FrameDistancesIn) { - double maxdist = 0.0; - frame_iterator frame1_end = frameList_.end(); - --frame1_end; - for (frame_iterator frm1 = frameList_.begin(); frm1 != frameList_.end(); ++frm1) - { - frame_iterator frm2 = frm1; - ++frm2; - for (; frm2 != frameList_.end(); ++frm2) { - double fdist = FrameDistancesIn.GetFdist(*frm1, *frm2); - if (fdist > maxdist) - maxdist = fdist; - } - } - eccentricity_ = maxdist; -} - -/** Calculate average distance between all members in cluster and - * the centroid. - */ -double ClusterNode::CalcAvgToCentroid( ClusterDist* Cdist ) const -{ - double avgdist = 0.0; - //int idx = 0; // DEBUG - //mprintf("AVG DISTANCES FOR CLUSTER %d:\n", Num()); // DEBUG - for (frame_iterator frm = frameList_.begin(); frm != frameList_.end(); ++frm) - { - double dist = Cdist->FrameCentroidDist( *frm, centroid_ ); - //mprintf("\tDist to %i is %f\n", idx++, dist); // DEBUG - avgdist += dist; - } - return ( avgdist / (double)frameList_.size() ); -} - -void ClusterNode::SortFrameList() { - std::sort(frameList_.begin(), frameList_.end()); -} - -// ClusterNode::HasFrame() -bool ClusterNode::HasFrame(int frame) const { - ClusterDist::Cframes::const_iterator it = std::find(frameList_.begin(), frameList_.end(), frame); - return !(it == frameList_.end()); -} - -// ClusterNode::RemoveFrameFromCluster() -void ClusterNode::RemoveFrameFromCluster(int frame) { - ClusterDist::Cframes::iterator pend = std::remove( frameList_.begin(), frameList_.end(), frame); - size_t newsize = pend - frameList_.begin(); - frameList_.resize( newsize ); -} - -void ClusterNode::RemoveFrameUpdateCentroid(ClusterDist* Cdist, int frame) { - Cdist->FrameOpCentroid(frame, centroid_, (double)frameList_.size(), - ClusterDist::SUBTRACTFRAME); - RemoveFrameFromCluster( frame ); -} - -void ClusterNode::AddFrameUpdateCentroid(ClusterDist* Cdist, int frame) { - Cdist->FrameOpCentroid(frame, centroid_, (double)frameList_.size(), - ClusterDist::ADDFRAME); - AddFrameToCluster( frame ); -} diff --git a/src/ClusterNode.h b/src/ClusterNode.h deleted file mode 100644 index 313b054a77..0000000000 --- a/src/ClusterNode.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef INC_CLUSTERNODE_H -#define INC_CLUSTERNODE_H -#include "ClusterDist.h" -#include "DataSet_Cmatrix.h" -/// Hold information for a cluster in a ClusterList -class ClusterNode { - public: - ClusterNode(); - ~ClusterNode(); - ClusterNode(ClusterDist*,ClusterDist::Cframes const&, int); - ClusterNode(const ClusterNode&); - ClusterNode& operator=(const ClusterNode&); - /// Used to pair a representative frame number with a score. - typedef std::pair RepPair; - /// Used to hold a list of representative frames/scores - typedef std::vector RepPairArray; - /// Used to sort clusters by # of frames in cluster - inline bool operator<(const ClusterNode&) const; - /// Merge frames from another cluster to this cluster - inline void MergeFrames(ClusterNode const&); - /// Find and set frame in the cluster that has lowest distance to all other frames. -// int SetBestRep_CumulativeDist(DataSet_Cmatrix const&); - /// Calculate eccentricity for frames in this cluster. - void CalcEccentricity(DataSet_Cmatrix const&); - /// Calculate centroid of members of this cluster. - void CalculateCentroid(ClusterDist* Cdist) { - if (centroid_ == 0) - centroid_ = Cdist->NewCentroid( frameList_ ); - else - Cdist->CalculateCentroid( centroid_, frameList_ ); - } - /// Calculate average distance of all members to centroid - double CalcAvgToCentroid( ClusterDist*) const; - // Iterator over frame numbers - typedef ClusterDist::Cframes::const_iterator frame_iterator; - frame_iterator beginframe() const { return frameList_.begin(); } - frame_iterator endframe() const { return frameList_.end(); } - /// \return Frame number at given index. - int ClusterFrame(int idx) const { return frameList_[idx]; } - /// \return cluster eccentricity - double Eccentricity() const { return eccentricity_; } - /// \return internal cluster number - int Num() const { return num_; } - /// \return number of frames in cluster. - int Nframes() const { return (int)frameList_.size(); } - /// \return best representative frame number, or -1 if no best rep set. - int BestRepFrame() const { - if (bestReps_.empty()) - return -1; - else - return bestReps_.front().first; - } - Centroid* Cent() const { return centroid_; } - std::string const& Cname() const { return name_; } - double RefRms() const { return refRms_; } - // Set internal variables - void AddFrameToCluster(int fnum) { frameList_.push_back( fnum ); } - void SetNum(int numIn) { num_ = numIn; } - /// Access representative frame list - RepPairArray const& BestReps() const { return bestReps_; } - RepPairArray& BestReps() { return bestReps_; } - inline void SetNameAndRms(std::string const&, double); - /// Sort internal frame list - void SortFrameList(); - /// \return true if given frame is in this cluster. - bool HasFrame(int) const; - /// Remove specified frame from cluster if present. - void RemoveFrameFromCluster(int); - /// Remove specified frame from cluster and update centroid. - void RemoveFrameUpdateCentroid(ClusterDist*, int); - /// Add specified frame to cluster and update centroid. - void AddFrameUpdateCentroid(ClusterDist*, int); - private: - double eccentricity_; ///< Maximum distance between any 2 frames. - double refRms_; ///< Cluster rms to reference (if assigned) - int num_; ///< Cluster number. - RepPairArray bestReps_; ///< List of best representative frames with scores. - ClusterDist::Cframes frameList_; ///< List of frames belonging to this cluster. - Centroid* centroid_; ///< Centroid of all frames in this cluster. - std::string name_; ///< Cluster name assigned from reference. -}; -// ----- INLINE FUNCTIONS ------------------------------------------------------ -/** Use > since we give higher priority to larger clusters. */ -bool ClusterNode::operator<(const ClusterNode& rhs) const { - return ( frameList_.size() > rhs.frameList_.size() ); -} -/** Frames from rhs go to this cluster. */ -void ClusterNode::MergeFrames( ClusterNode const& rhs) { - frameList_.insert(frameList_.end(), rhs.frameList_.begin(), rhs.frameList_.end()); -} - -void ClusterNode::SetNameAndRms(std::string const& nameIn, double rmsIn) { - name_ = nameIn; - refRms_ = rmsIn; -} -#endif diff --git a/src/ClusterSieve.cpp b/src/ClusterSieve.cpp deleted file mode 100644 index f6f99ec4c3..0000000000 --- a/src/ClusterSieve.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "ClusterSieve.h" -#include "Random.h" - -// CONSTRUCTOR -ClusterSieve::ClusterSieve() : type_(NONE), sieve_(1), actualNframes_(0) {} - -void ClusterSieve::Clear() { - frameToIdx_.clear(); - type_ = NONE; - sieve_ = 1; - actualNframes_ = 0; -} - -inline void ClusterSieve::DetermineTypeFromSieve( int sieveIn ) { - sieve_ = sieveIn; - // Determine sieve type from sieve value. - if (sieve_ < -1) - type_ = RANDOM; - else if (sieve_ < 2) { - type_ = NONE; - sieve_ = 1; - } else - type_ = REGULAR; -} - -// ClusterSieve::SetSieve() -int ClusterSieve::SetSieve(int sieveIn, size_t maxFrames, int iseed) { - if (maxFrames < 1) return 1; - DetermineTypeFromSieve( sieveIn ); - frameToIdx_.clear(); - if (type_ == NONE) - { // No sieving; frame == index - frameToIdx_.reserve( maxFrames ); - for (unsigned int i = 0; i < maxFrames; i++) - frameToIdx_.push_back( i ); - actualNframes_ = (int)maxFrames; - } - else if (type_ == REGULAR) - { // Regular sieveing; index = frame / sieve - frameToIdx_.assign( maxFrames, -1 ); - int idx = 0; - for (unsigned int i = 0; i < maxFrames; i += sieve_) - frameToIdx_[i] = idx++; - actualNframes_ = idx; - } - else if (type_ == RANDOM) - { // Random sieving; maxframes / sieve random indices - frameToIdx_.assign( maxFrames, -1 ); - unsigned int maxidx = maxFrames - 1; - Random_Number random; - random.rn_set( iseed ); - for (unsigned int i = 0; i < maxFrames; i -= sieve_) - { - bool frame_generated = false; - // Pick until we pick a frame that has not yet been selected. - while (!frame_generated) { - unsigned int iframe = random.rn_num_interval(0, maxidx); - if (frameToIdx_[iframe] == -1) { - frameToIdx_[iframe] = 1; - frame_generated = true; - } - } - } - // Put indices in order - int idx = 0; - for (unsigned int i = 0; i < maxFrames; i++) - if (frameToIdx_[i] == 1) - frameToIdx_[i] = idx++; - actualNframes_ = idx; - } - MakeIdxToFrame(); - return 0; -} - -// ClusterSieve::SetSieve() -int ClusterSieve::SetSieve(int sieveIn, std::vector const& sieveStatus) { - DetermineTypeFromSieve( sieveIn ); - if (sieveStatus.empty()) return 1; - frameToIdx_.clear(); - frameToIdx_.assign( sieveStatus.size(), -1 ); - unsigned int idx = 0; - for (unsigned int frame = 0; frame < sieveStatus.size(); ++frame) - { - if ( sieveStatus[frame] == 'F' ) - frameToIdx_[frame] = idx++; - } - actualNframes_ = (int)idx; - MakeIdxToFrame(); - return 0; -} - -// ClusterSieve::MakeIdxToFrame() -void ClusterSieve::MakeIdxToFrame() { - idxToFrame_.clear(); - idxToFrame_.reserve( actualNframes_ ); - for (unsigned int frame = 0; frame != frameToIdx_.size(); frame++) - { - if (frameToIdx_[frame] != -1) - idxToFrame_.push_back( frame ); - } -} - -size_t ClusterSieve::DataSize() const { - return ( sizeof(type_) + sizeof(int) + - (frameToIdx_.capacity()*sizeof(int) + sizeof(frameToIdx_)) + - (idxToFrame_.capacity()*sizeof(int) + sizeof(idxToFrame_)) ); -} diff --git a/src/ClusterSieve.h b/src/ClusterSieve.h deleted file mode 100644 index 11c42e8277..0000000000 --- a/src/ClusterSieve.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef INC_CLUSTERSIEVE_H -#define INC_CLUSTERSIEVE_H -#include -#include -/// Used to map actual frame numbers to ClusterMatrix internal indices. -class ClusterSieve { - public: - enum SieveType { NONE=0, REGULAR, RANDOM }; - typedef std::vector SievedFrames; - ClusterSieve(); - void Clear(); - /// Setup no sieve, regular sieve, or random sieve. - int SetSieve(int, size_t, int); - /// Setup sieve from array: 'T'=sieved, 'F'=not sieved. - int SetSieve(int, std::vector const&); - /// \return array of frames that will actually be clustered. - SievedFrames const& Frames() const { return idxToFrame_; } - /// \return size of data in bytes - size_t DataSize() const; - /// \return an array index corresponding to a sieved frame. - inline int FrameToIdx(int frame) const { return frameToIdx_[frame]; } - /// \return frame number correspnding to array index. - inline int IdxToFrame(int idx) const { return idxToFrame_[idx]; } - /// \return Original max number of frames. - inline size_t MaxFrames() const { return frameToIdx_.size(); } - /// \return Actual number of frames after sieving. - inline int ActualNframes() const { return actualNframes_; } - /// \return Sieve value. - inline int Sieve() const { return sieve_; } - /// \return Sieve type. - inline SieveType Type() const { return type_; } - private: - inline void DetermineTypeFromSieve(int); - void MakeIdxToFrame(); - SieveType type_; ///< Sieve type. - int sieve_; ///< Sieve value; > 1 is regular, < -1 is random. - int actualNframes_; ///< Actual number of frames after sieving. - std::vector frameToIdx_; ///< Frame number to matrix index; -1 if frame was sieved out. - std::vector idxToFrame_; ///< Matrix index to frame number (size: actualNframes_). -}; -#endif diff --git a/src/Cluster_HierAgglo.cpp b/src/Cluster_HierAgglo.cpp deleted file mode 100644 index b727395d31..0000000000 --- a/src/Cluster_HierAgglo.cpp +++ /dev/null @@ -1,367 +0,0 @@ -#include // std::min, std::max -#include // DBL_MAX -#include "Cluster_HierAgglo.h" -#include "CpptrajStdio.h" -#include "ProgressBar.h" - -Cluster_HierAgglo::Cluster_HierAgglo() : - nclusters_(-1), - epsilon_(-1.0), - linkage_(AVERAGELINK), - includeSievedFrames_(false) -{} - -void Cluster_HierAgglo::Help() { - mprintf("\t[hieragglo [epsilon ] [clusters ] [linkage|averagelinkage|complete]\n" - "\t [epsilonplot ] [includesieved_cdist]]\n"); -} - -static const char* LinkageString[] = { - "single-linkage", "average-linkage", "complete-linkage" -}; - -int Cluster_HierAgglo::SetupCluster(ArgList& analyzeArgs) { - nclusters_ = analyzeArgs.getKeyInt("clusters", -1); - epsilon_ = analyzeArgs.getKeyDouble("epsilon", -1.0); - if (analyzeArgs.hasKey("linkage")) linkage_ = SINGLELINK; - else if (analyzeArgs.hasKey("averagelinkage")) linkage_ = AVERAGELINK; - else if (analyzeArgs.hasKey("complete")) linkage_ = COMPLETELINK; - else linkage_ = AVERAGELINK; // DEFAULT linkage - includeSievedFrames_ = analyzeArgs.hasKey("includesieved_cdist"); - std::string epsilonPlot = analyzeArgs.GetStringKey("epsilonplot"); - if (!epsilonPlot.empty()) { - if (eps_v_n_.OpenWrite( epsilonPlot )) return 1; - eps_v_n_.Printf("%-12s %12s\n", "#Epsilon", "Nclusters"); - } - // Determine finish criteria. If nothing specified default to 10 clusters. - if (nclusters_==-1 && epsilon_==-1.0) { - mprintf("Warning: cluster: Neither target # of clusters nor epsilon given.\n"); - nclusters_ = 10; - mprintf("Warning: cluster: Defaulting to %i clusters.\n", nclusters_); - } - return 0; -} - -void Cluster_HierAgglo::ClusteringInfo() const { - mprintf("\tHierarchical Agglomerative:"); - if (nclusters_ != -1) - mprintf(" %i clusters,",nclusters_); - if (epsilon_ != -1.0) - mprintf(" epsilon %.3f,",epsilon_); - mprintf(" %s.\n", LinkageString[linkage_]); - if (eps_v_n_.IsOpen()) - mprintf("\tWriting epsilon vs # clusters to '%s'\n", eps_v_n_.Filename().full()); - if (includeSievedFrames_) - mprintf("\tSieved frames will be included in final cluster distance calculation.\n" - "Warning: 'includesieved_cdist' may be very slow.\n"); - else - mprintf("\tSieved frames will not be included in final cluster distance calculation.\n"); -} - -/** Set up the initial distances between clusters. Should be called before - * any clustering is performed. - */ -void Cluster_HierAgglo::InitializeClusterDistances() { - // Sets up matrix and ignore array - ClusterDistances_.SetupMatrix( clusters_.size() ); - // Build initial cluster distances. Take advantage of the fact that - // the initial cluster layout is the same as the pairwise array. - unsigned int total_frames = FrameDistances().FramesToCluster().size(); - for (unsigned int idx1 = 0; idx1 != total_frames; idx1++) { - int f1 = FrameDistances().FramesToCluster()[ idx1 ]; - for (unsigned int idx2 = idx1 + 1; idx2 != total_frames; idx2++) { - int f2 = FrameDistances().FramesToCluster()[ idx2 ]; - ClusterDistances_.SetCdist( idx1, idx2, FrameDistances().GetFdist(f1, f2) ); - } - } - if (debug_ > 1) { - mprintf("CLUSTER: INITIAL CLUSTER DISTANCES:\n"); - ClusterDistances_.PrintElements(); - } -} - -/** Cluster using a hierarchical agglomerative (bottom-up) approach. All frames - * start in their own cluster. The closest two clusters are merged, and - * distances between the newly merged cluster and all remaining clusters are - * recalculated according to one of the following metrics: - * - single-linkage : The minimum distance between frames in clusters are used. - * - average-linkage : The average distance between frames in clusters are used. - * - complete-linkage: The maximum distance between frames in clusters are used. - */ -int Cluster_HierAgglo::Cluster() { - // If epsilon not given make it huge - if (epsilon_ == -1.0) epsilon_ = DBL_MAX; - // If target clusters not given make it 1 - if (nclusters_ == -1) nclusters_ = 1; - mprintf("\tStarting Hierarchical Agglomerative Clustering:\n"); - ProgressBar cluster_progress(-10); - // Build initial clusters. - for (int frame = 0; frame < (int)FrameDistances().OriginalNframes(); frame++) { - if (!FrameDistances().FrameWasSieved( frame )) - AddCluster( ClusterDist::Cframes(1, frame) ); - } - mprintf("\t%i initial clusters.\n", Nclusters()); - // Build initial cluster distance matrix. - InitializeClusterDistances(); - // DEBUG - print initial clusters - if (debug_ > 1) - PrintClusters(); - bool clusteringComplete = false; - int iterations = 0; - while (!clusteringComplete) { - // Merge 2 closest clusters. Clustering complete if closest dist > epsilon. - if (MergeClosest()) break; - // If the target number of clusters is reached we are done - if (Nclusters() <= nclusters_) { - mprintf("\n\tTarget # of clusters (%i) met (%u), clustering complete.\n", nclusters_, - Nclusters()); - break; - } - if (Nclusters() == 1) clusteringComplete = true; // Sanity check - cluster_progress.Update( iterations++ ); - } - mprintf("\tCompleted after %i iterations, %u clusters.\n",iterations, - Nclusters()); - return 0; -} - -void Cluster_HierAgglo::ClusterResults(CpptrajFile& outfile) const { - outfile.Printf("#Algorithm: HierAgglo linkage %s nclusters %i epsilon %g\n", - LinkageString[linkage_], nclusters_, epsilon_); -} - -#ifdef TIMER -void Cluster_HierAgglo::Timing(double total) const { - time_findMin_.WriteTiming(2, "Find min distance", total); - time_mergeFrames_.WriteTiming(2, "Merge cluster frames", total); - time_calcLinkage_.WriteTiming(2, "Calculate new linkage", total); -} -#endif - -/** Find and merge the two closest clusters. */ -int Cluster_HierAgglo::MergeClosest() { - int C1, C2; - // Find the minimum distance between clusters. C1 will be lower than C2. -# ifdef TIMER - time_findMin_.Start(); -# endif - double min = ClusterDistances_.FindMin(C1, C2); -# ifdef TIMER - time_findMin_.Stop(); -# endif - if (eps_v_n_.IsOpen()) - eps_v_n_.Printf("%12g %12i\n", min, Nclusters()); - if (debug_>0) - mprintf("\tMinimum found between clusters %i and %i (%f)\n",C1,C2,min); - // If the minimum distance is greater than epsilon we are done - if (min > epsilon_) { - mprintf("\n\tMinimum distance (%f) is greater than epsilon (%f), clustering complete.\n", - min, epsilon_); - return 1; - } - - // Find C1, the number of the cluster to be merged into. - cluster_it C1_it = clusters_.begin(); - for (; C1_it != clusters_.end(); ++C1_it) - { - if ( C1_it->Num() == C1 ) break; - } - if (C1_it == clusters_.end()) { - mprinterr("Error: MergeClosest: C1 (%i) not found.\n",C1); - return 1; - } - // Find C2 - start from C1 since C1 < C2 - cluster_it C2_it = C1_it; - for (; C2_it != clusters_.end(); ++C2_it) { - if ( C2_it->Num() == C2 ) break; - } - if (C2_it == clusters_.end()) { - mprinterr("Error: MergeClosest: C2 (%i) not found.\n",C2); - return 1; - } - - // Merge the closest clusters, C2 -> C1, remove C2 -# ifdef TIMER - time_mergeFrames_.Start(); -# endif - C1_it->MergeFrames( *C2_it ); - clusters_.erase( C2_it ); -# ifdef TIMER - time_mergeFrames_.Stop(); -# endif - // DEBUG - if (debug_>1) { - mprintf("\nAFTER MERGE of %i and %i:\n",C1,C2); - PrintClusters(); - } - // Remove all distances having to do with C2 - ClusterDistances_.Ignore(C2); -# ifdef TIMER - time_calcLinkage_.Start(); -# endif - switch (linkage_) { - case AVERAGELINK : calcAvgDist(C1_it); break; - case SINGLELINK : calcMinDist(C1_it); break; - case COMPLETELINK: calcMaxDist(C1_it); break; - } -# ifdef TIMER - time_calcLinkage_.Stop(); -# endif - if (debug_>2) { - mprintf("NEW CLUSTER DISTANCES:\n"); - ClusterDistances_.PrintElements(); - } - - return 0; -} - -// Cluster_HierAgglo::ClusterDistance() -double Cluster_HierAgglo::ClusterDistance(ClusterNode const& C1, ClusterNode const& C2) const { - double dist = 0.0; - if (includeSievedFrames_) { - if (linkage_ == AVERAGELINK) { - for (ClusterNode::frame_iterator f1 = C1.beginframe(); f1 != C1.endframe(); ++f1) - { - for (ClusterNode::frame_iterator f2 = C2.beginframe(); f2 != C2.endframe(); ++f2) - dist += Frame_Distance(*f1, *f2); - } - dist /= (double)(C1.Nframes() * C2.Nframes()); - } else if (linkage_ == SINGLELINK) { // min - dist = DBL_MAX; - for (ClusterNode::frame_iterator f1 = C1.beginframe(); f1 != C1.endframe(); ++f1) - { - for (ClusterNode::frame_iterator f2 = C2.beginframe(); f2 != C2.endframe(); ++f2) - dist = std::min( Frame_Distance(*f1, *f2), dist ); - } - } else if (linkage_ == COMPLETELINK) { // max - dist = -1.0; - for (ClusterNode::frame_iterator f1 = C1.beginframe(); f1 != C1.endframe(); ++f1) - { - for (ClusterNode::frame_iterator f2 = C2.beginframe(); f2 != C2.endframe(); ++f2) - dist = std::max( Frame_Distance(*f1, *f2), dist ); - } - } - } else { - // Ignore sieved frames. - switch (linkage_) { - case AVERAGELINK : dist = 0.0; break; - case SINGLELINK : dist = DBL_MAX; break; - case COMPLETELINK: dist = -1.0; break; - } - unsigned int Nelements = 0; - for (ClusterNode::frame_iterator f1 = C1.beginframe(); f1 != C1.endframe(); ++f1) - { - if (!FrameDistances().FrameWasSieved( *f1 )) { - for (ClusterNode::frame_iterator f2 = C2.beginframe(); f2 != C2.endframe(); ++f2) - { - if (!FrameDistances().FrameWasSieved( *f2 )) { - switch (linkage_) { - case AVERAGELINK : dist += Frame_Distance(*f1, *f2); ++Nelements; break; - case SINGLELINK : dist = std::min( Frame_Distance(*f1, *f2), dist ); break; - case COMPLETELINK: dist = std::max( Frame_Distance(*f1, *f2), dist ); break; - } - } - } - } - } - if (linkage_ == AVERAGELINK) dist /= (double)Nelements; - } - if (debug_ > 0) - mprintf("DEBUG: Calc dist between clusters %i (%i frames) and %i (%i frames), %g\n", - C1.Num(), C1.Nframes(), C2.Num(), C2.Nframes(), dist); - return dist; -} - -/** Calculate the minimum distance between frames in cluster specified by - * iterator C1 and frames in all other clusters. - */ -void Cluster_HierAgglo::calcMinDist(cluster_it& C1_it) -{ - // All cluster distances to C1 must be recalcd. - for (cluster_it C2_it = clusters_.begin(); - C2_it != clusters_.end(); ++C2_it) - { - if (C2_it == C1_it) continue; - //mprintf("\t\tRecalc distance between %i and %i:\n",C1,newc2); - // Pick the minimum distance between newc2 and C1 - double min = DBL_MAX; - for (ClusterNode::frame_iterator c1frames = C1_it->beginframe(); - c1frames != C1_it->endframe(); - ++c1frames) - { - for (ClusterNode::frame_iterator c2frames = C2_it->beginframe(); - c2frames != C2_it->endframe(); - ++c2frames) - { - double Dist = FrameDistances().GetFdist(*c1frames, *c2frames); - //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); - if ( Dist < min ) min = Dist; - } - } - //mprintf("\t\tMin distance between %i and %i: %f\n",C1,newc2,min); - ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), min ); - } -} - -/** Calculate the maximum distance between frames in cluster specified by - * iterator C1 and frames in all other clusters. - */ -void Cluster_HierAgglo::calcMaxDist(cluster_it& C1_it) -{ - // All cluster distances to C1 must be recalcd. - for (cluster_it C2_it = clusters_.begin(); - C2_it != clusters_.end(); ++C2_it) - { - if (C2_it == C1_it) continue; - //mprintf("\t\tRecalc distance between %i and %i:\n",C1,newc2); - // Pick the maximum distance between newc2 and C1 - double max = -1.0; - for (ClusterNode::frame_iterator c1frames = C1_it->beginframe(); - c1frames != C1_it->endframe(); - ++c1frames) - { - for (ClusterNode::frame_iterator c2frames = C2_it->beginframe(); - c2frames != C2_it->endframe(); - ++c2frames) - { - double Dist = FrameDistances().GetFdist(*c1frames, *c2frames); - //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); - if ( Dist > max ) max = Dist; - } - } - //mprintf("\t\tMax distance between %i and %i: %f\n",C1,newc2,max); - ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), max ); - } -} - -/** Calculate the average distance between frames in cluster specified by - * iterator C1 and frames in all other clusters. - */ -void Cluster_HierAgglo::calcAvgDist(cluster_it& C1_it) -{ - // All cluster distances to C1 must be recalcd. - for (cluster_it C2_it = clusters_.begin(); - C2_it != clusters_.end(); ++C2_it) - { - if (C2_it == C1_it) continue; - //mprintf("\t\tRecalc distance between %i and %i:\n",(*C1_it).Num(),(*C2_it).Num()); - // Pick the minimum distance between newc2 and C1 - double sumDist = 0; - for (ClusterNode::frame_iterator c1frames = C1_it->beginframe(); - c1frames != C1_it->endframe(); - ++c1frames) - { - for (ClusterNode::frame_iterator c2frames = C2_it->beginframe(); - c2frames != C2_it->endframe(); - ++c2frames) - { - double Dist = FrameDistances().GetFdist(*c1frames, *c2frames); - //mprintf("\t\t\tFrame %i to frame %i = %f\n",*c1frames,*c2frames,Dist); - sumDist += Dist; - } - } - double Dist = sumDist / (double)(C1_it->Nframes() * C2_it->Nframes()); - //mprintf("\t\tAvg distance between %i and %i: %f\n",(*C1_it).Num(),(*C2_it).Num(),Dist); - ClusterDistances_.SetCdist( C1_it->Num(), C2_it->Num(), Dist ); - } -} diff --git a/src/Cluster_HierAgglo.h b/src/Cluster_HierAgglo.h deleted file mode 100644 index 02829add47..0000000000 --- a/src/Cluster_HierAgglo.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef INC_CLUSTER_HIERAGGLO_H -#define INC_CLUSTER_HIERAGGLO_H -#include "ClusterList.h" -#include "ClusterMatrix.h" -#ifdef TIMER -# include "Timer.h" -#endif -class Cluster_HierAgglo : public ClusterList { - public: - Cluster_HierAgglo(); - static void Help(); - int SetupCluster(ArgList&); - void ClusteringInfo() const; - int Cluster(); - /// \return Distance between given clusters based on current linkage - double ClusterDistance(ClusterNode const&, ClusterNode const&) const; -# ifdef TIMER - void Timing(double) const; -# endif - void AddSievedFrames() { AddSievedFramesByCentroid(); } - void ClusterResults(CpptrajFile&) const; - private: - void InitializeClusterDistances(); - int MergeClosest(); - void calcMinDist(cluster_it&); - void calcMaxDist(cluster_it&); - void calcAvgDist(cluster_it&); - - /// Type of distance calculation between clusters. - enum LINKAGETYPE { SINGLELINK = 0, AVERAGELINK, COMPLETELINK }; - int nclusters_; ///< Target # of clusters. - double epsilon_; ///< Once the min distance between clusters is > epsilon, stop. - LINKAGETYPE linkage_; ///< Cluster Linkage type. - bool includeSievedFrames_; ///< If true include sieved frames in ClusterDistance() calc. - CpptrajFile eps_v_n_; ///< Write epsilon vs # clusters. - ClusterMatrix ClusterDistances_; -# ifdef TIMER - Timer time_findMin_; - Timer time_mergeFrames_; - Timer time_calcLinkage_; -# endif -}; -#endif diff --git a/src/Cluster_Kmeans.cpp b/src/Cluster_Kmeans.cpp deleted file mode 100644 index 09a9b1c143..0000000000 --- a/src/Cluster_Kmeans.cpp +++ /dev/null @@ -1,275 +0,0 @@ -#include "Cluster_Kmeans.h" -#include "CpptrajStdio.h" -#include "ProgressBar.h" - -Cluster_Kmeans::Cluster_Kmeans() : - nclusters_(0), - kseed_(-1), - maxIt_(100), - mode_(SEQUENTIAL), - clusterToClusterCentroid_(false) -{} - -void Cluster_Kmeans::Help() { - mprintf("\t[kmeans clusters [randompoint [kseed ]] [maxit ]\n"); -} - -// Cluster_Kmeans::SetupCluster() -int Cluster_Kmeans::SetupCluster(ArgList& analyzeArgs) { - nclusters_ = analyzeArgs.getKeyInt("clusters", -1); - if (nclusters_ < 2) { - mprinterr("Error: Specify number of clusters > 1 for K-means algorithm.\n"); - return 1; - } - if (analyzeArgs.hasKey("randompoint")) - mode_ = RANDOM; - else - mode_ = SEQUENTIAL; - kseed_ = analyzeArgs.getKeyInt("kseed", -1); - maxIt_ = analyzeArgs.getKeyInt("maxit", 100); - return 0; -} - -// Cluster_Kmeans::ClusteringInfo() -void Cluster_Kmeans::ClusteringInfo() const { - mprintf("\tK-MEANS: Looking for %i clusters.\n", nclusters_); - if (mode_ == SEQUENTIAL) - mprintf("\t\tSequentially modify each point.\n"); - else - mprintf("\t\tRandomly pick points for modification.\n"); - if (kseed_ != -1 && mode_ == RANDOM) - mprintf("\t\tSeed for random number generator: %i\n", kseed_); - mprintf("\tCluster to cluster distance will be based on"); - if (clusterToClusterCentroid_) - mprintf(" best representative from cluster.\n"); - else - mprintf(" cluster centroids.\n"); -} - -// Cluster_Kmeans::ClusterResults() -void Cluster_Kmeans::ClusterResults(CpptrajFile& outfile) const { - outfile.Printf("#Algorithm: Kmeans nclusters %i maxit %i\n", nclusters_, maxIt_); -} - -// Cluster_Kmeans::Cluster() -int Cluster_Kmeans::Cluster() { - // First determine which frames are being clustered. - Iarray const& FramesToCluster = FrameDistances().FramesToCluster(); - - // Determine seeds - FindKmeansSeeds( FramesToCluster ); - - if (mode_ == RANDOM) - RN_.rn_set( kseed_ ); - - int pointCount = (int)FramesToCluster.size(); - - // This array will hold the indices of the points to process each iteration. - // If sequential this is just 0 -> pointCount. If random this will be - // reassigned each iteration. - Iarray PointIndices; - PointIndices.reserve( pointCount ); - for (int processIdx = 0; processIdx != pointCount; processIdx++) - PointIndices.push_back( processIdx ); - - // Add the seed clusters - for (Iarray::const_iterator seedIdx = SeedIndices_.begin(); - seedIdx != SeedIndices_.end(); ++seedIdx) - { - int seedFrame = FramesToCluster[ *seedIdx ]; - // A centroid is created for new clusters. - AddCluster( ClusterDist::Cframes(1, seedFrame) ); - // NOTE: No need to calc best rep frame, only 1 frame. - if (debug_ > 0) - mprintf("Put frame %i in cluster %i (seed index=%i).\n", - seedFrame, clusters_.back().Num(), *seedIdx); - } - // Assign points in 3 passes. If a point looked like it belonged to cluster A - // at first, but then we added many other points and altered our cluster - // shapes, its possible that we will want to reassign it to cluster B. - for (int iteration = 0; iteration != maxIt_; iteration++) - { - if (mode_ == RANDOM) { - RN_.ShufflePoints( PointIndices ); - if (debug_ > 0) { - mprintf("DEBUG: Shuffled points:"); - for (Iarray::const_iterator it = PointIndices.begin(); - it != PointIndices.end(); ++it) - mprintf(" %i", *it); - mprintf("\n"); - } - } - - // Add each point to an existing cluster, and recompute centroid - mprintf("\tRound %i: ", iteration); - ProgressBar progress( PointIndices.size() ); - int Nchanged = 0; - int prog = 0; - for (Iarray::const_iterator pointIdx = PointIndices.begin(); - pointIdx != PointIndices.end(); ++pointIdx, ++prog) - { - if (debug_ < 1) progress.Update( prog ); - int oldClusterIdx = -1; -// if ( iteration != 0 || mode_ != SEQUENTIAL) // FIXME: Should this really happen for RANDOM -// { - int pointFrame = FramesToCluster[ *pointIdx ]; - if (debug_ > 0) - mprintf("DEBUG: Processing frame %i (index %i)\n", pointFrame, *pointIdx); - bool pointWasYanked = true; - if (iteration > 0) { - // Yank this point out of its cluster, recompute the centroid - for (cluster_it C1 = clusters_.begin(); C1 != clusters_.end(); ++C1) - { - if (C1->HasFrame( pointFrame )) - { - // If this point is alone in its cluster its in the right place - if (C1->Nframes() == 1) { - pointWasYanked = false; - continue; // FIXME: should this be a break? - } - //oldBestRep = C1->BestRepFrame(); - oldClusterIdx = C1->Num(); - C1->RemoveFrameUpdateCentroid( Cdist_, pointFrame ); // TEST -// C1->RemoveFrameFromCluster( pointFrame ); - //newBestRep = C1->FindBestRepFrame(); -// C1->CalculateCentroid( Cdist_ ); - if (debug_ > 0) - mprintf("Remove Frame %i from cluster %i\n", pointFrame, C1->Num()); - //if (clusterToClusterCentroid_) { - // if (oldBestRep != NewBestRep) - // C1->AlignToBestRep( Cdist_ ); // FIXME: Only relevant for COORDS dist? - // C1->CalculateCentroid( Cdist_ ); // FIXME: Seems unnessecary to align prior - //} - } - } - } else { - // First iteration. If this point is already in a cluster it is a seed. - for (cluster_it C1 = clusters_.begin(); C1 != clusters_.end(); ++C1) - { - if (C1->HasFrame( pointFrame )) { - pointWasYanked = false; - if (debug_ > 0) - mprintf("Frame %i was already used to seed cluster %i\n", - pointFrame, C1->Num()); - continue; // FIXME break? - } - } - } - if (pointWasYanked) { - // Find out what cluster this point is now closest to. - double closestDist = -1.0; - cluster_it closestCluster = clusters_.begin(); - for (cluster_it C1 = clusters_.begin(); C1 != clusters_.end(); ++C1) - { - double dist = Cdist_->FrameCentroidDist(pointFrame, C1->Cent()); - if (closestDist < 0.0 || dist < closestDist) - { - closestDist = dist; - closestCluster = C1; - } - } - //oldBestRep = closestCluster->BestRepFrame(); - closestCluster->AddFrameUpdateCentroid( Cdist_, pointFrame ); // TEST -// closestCluster->AddFrameToCluster( pointFrame ); - //newBestRep = closestCluster->FindBestFrameFrame(); -// closestCluster->CalculateCentroid( Cdist_ ); - if (closestCluster->Num() != oldClusterIdx) - { - Nchanged++; - if (debug_ > 0) - mprintf("Remove Frame %i from cluster %i, but add to cluster %i (dist= %f).\n", - pointFrame, oldClusterIdx, closestCluster->Num(), closestDist); - } else { - if (debug_ > 0) - mprintf("Frame %i staying in cluster %i\n", pointFrame, closestCluster->Num()); - } - if (clusterToClusterCentroid_) { - //if (oldBestRep != NewBestRep) { - // C1->AlignToBestRep( Cdist_ ); // FIXME: Only relevant for COORDS dist? - // C1->CalculateCentroid( Cdist_ ); // FIXME: Seems unnessecary to align prior - //} - } - } -// } - } // END loop over points to cluster - if (Nchanged == 0) { - mprintf("\tK-means round %i: No change. Skipping the rest of the iterations.\n", iteration); - break; - } else - mprintf("\tK-means round %i: %i points changed cluster assignment.\n", iteration, Nchanged); - } // END k-means iterations - // Remove any empty clusters - // FIXME: Will there ever be empty clusters? - RemoveEmptyClusters(); - // NOTE in PTRAJ here align all frames to best rep - return 0; -} - -// Cluster_Kmeans::FindKmeansSeeds() -/** Find some seed-points for K-means clustering. Take the first point as an - * arbitrary first choice. Then, at each iteration, add the point whose total - * distance from our set of seeds is as large as possible. - */ -int Cluster_Kmeans::FindKmeansSeeds(Iarray const& FramesToCluster) { - // SeedIndices will hold indices into FramesToCluster - SeedIndices_.resize( nclusters_, 1 ); // 1 used to be consistent with ptraj - - double bestDistance = 0.0; - int frameCount = (int)FramesToCluster.size(); - for (int frameIdx = 0; frameIdx != frameCount; frameIdx++) - { - int seedFrame = FramesToCluster[ frameIdx ]; - for (int candidateIdx = frameIdx; candidateIdx < frameCount; candidateIdx++) - { - int candidateFrame = FramesToCluster[ candidateIdx ]; - double dist = FrameDistances().GetFdist( seedFrame, candidateFrame ); - if (dist > bestDistance) - { - bestDistance = dist; - SeedIndices_[0] = frameIdx; - SeedIndices_[1] = candidateIdx; - } - } - } - - for (int seedIdx = 2; seedIdx != nclusters_; seedIdx++) - { - bestDistance = 0.0; - int bestIdx = 0; - for (int candidateIdx = 0; candidateIdx < frameCount; candidateIdx++) - { - // Make sure this candidate isnt already a seed - bool skipCandidate = false; - for (int checkIdx = 0; checkIdx != seedIdx; checkIdx++) - { - if (SeedIndices_[checkIdx] == candidateIdx) { - skipCandidate = true; - break; - } - } - if (!skipCandidate) { - // Get the closest distance from this candidate to a current seed - int candidateFrame = FramesToCluster[ candidateIdx ]; - double nearestDist = -1.0; - for (int checkIdx = 0; checkIdx != seedIdx; checkIdx++) - { - int seedFrame = FramesToCluster[ SeedIndices_[checkIdx] ]; - double dist = FrameDistances().GetFdist( candidateFrame, seedFrame ); - if (dist < nearestDist || nearestDist < 0.0) - nearestDist = dist; - } - // Is this the best so far? - if (nearestDist > bestDistance) - { - bestDistance = nearestDist; - bestIdx = candidateIdx; - } - } - } - SeedIndices_[seedIdx] = bestIdx; - } - if (debug_ > 0) - for (unsigned int si = 0; si != SeedIndices_.size(); si++) - mprintf("DEBUG:\t\tSeedIndices[%u]= %i\n", si, SeedIndices_[si]); - return 0; -} diff --git a/src/Cluster_Kmeans.h b/src/Cluster_Kmeans.h deleted file mode 100644 index 68ca64e5f4..0000000000 --- a/src/Cluster_Kmeans.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef INC_CLUSTER_KMEANS_H -#define INC_CLUSTER_KMEANS_H -#include "ClusterList.h" -#include "Random.h" -class Cluster_Kmeans : public ClusterList { - public: - Cluster_Kmeans(); - static void Help(); - int SetupCluster(ArgList&); - void ClusteringInfo() const; - int Cluster(); -# ifdef TIMER - void Timing(double) const {} -# endif - void AddSievedFrames() { AddSievedFramesByCentroid(); } - void ClusterResults(CpptrajFile&) const; - private: - typedef std::vector Iarray; - enum KmeansModeType { SEQUENTIAL, RANDOM }; - - int FindKmeansSeeds(Iarray const&); - - Random_Number RN_; - int nclusters_; ///< Target number of clusters. - int kseed_; - int maxIt_; - Iarray SeedIndices_; - KmeansModeType mode_; - bool clusterToClusterCentroid_; -}; -#endif diff --git a/src/Cluster_ReadInfo.cpp b/src/Cluster_ReadInfo.cpp deleted file mode 100644 index 7bed3af704..0000000000 --- a/src/Cluster_ReadInfo.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "Cluster_ReadInfo.h" -#include "CpptrajStdio.h" -#include "BufferedLine.h" - -Cluster_ReadInfo::Cluster_ReadInfo() {} - -void Cluster_ReadInfo::Help() { - mprintf("\t[{readtxt|readinfo} infofile ]\n"); -} - -int Cluster_ReadInfo::SetupCluster(ArgList& analyzeArgs) { - filename_ = analyzeArgs.GetStringKey("infofile"); - if (filename_.empty()) { - mprinterr("Error: No cluster info filename given.\n"); - return 1; - } - return 0; -} - -void Cluster_ReadInfo::ClusteringInfo() const { - mprintf("\tREADINFO: Reading cluster information from previous run, file %s.\n", - filename_.c_str()); -} - -static int Err(int code) { - switch (code) { - case 0: mprinterr("Error: Could not open info file.\n"); break; - case 1: mprinterr("Error: Unexpected end of info file.\n"); break; - case 2: mprinterr("Error: Invalid number of clusters in info file.\n"); break; - case 3: mprinterr("Error: Invalid number of frames in info file.\n"); break; - } - return 1; -} - -int Cluster_ReadInfo::Cluster() { - BufferedLine infile; - if (infile.OpenFileRead( filename_ )) return Err(0); - const char* ptr = infile.Line(); - if (ptr == 0) return Err(1); - ArgList infoLine( ptr, " " ); - int nclusters = infoLine.getKeyInt("#Clustering:", -1); - if (nclusters == -1) return Err(2); - int nframes = infoLine.getKeyInt("clusters", -1); - if (nframes == -1) return Err(3); - if (nframes != (int)FrameDistances().OriginalNframes()) { - mprinterr("Error: # frames in cluster info file (%i) does not match" - " current # frames (%i)\n", nframes, FrameDistances().OriginalNframes()); - return 1; - } - // Scan down to clusters - while (ptr[0] == '#') { - ptr = infile.Line(); - if (ptr == 0) return Err(1); - // Save previous clustering info. Includes newline. - if (ptr[1] == 'A' && ptr[2] == 'l' && ptr[3] == 'g') - algorithm_.assign( ptr + 12 ); // Right past '#Algorithm: ' - } - // Read clusters - ClusterDist::Cframes frames; - for (int cnum = 0; cnum != nclusters; cnum++) { - if (ptr == 0) return Err(1); - frames.clear(); - // TODO: Check for busted lines? - for (int fidx = 0; fidx != nframes; fidx++) { - if (ptr[fidx] == 'X') - frames.push_back( fidx ); - } - AddCluster( frames ); - mprintf("\tRead cluster %i, %zu frames.\n", cnum, frames.size()); - ptr = infile.Line(); - } - infile.CloseFile(); - return 0; -} - -void Cluster_ReadInfo::ClusterResults(CpptrajFile& outfile) const { - outfile.Printf("#Algorithm: Read from file '%s'\n", filename_.c_str()); - if (!algorithm_.empty()) - outfile.Printf("#Original algorithm: %s\n", algorithm_.c_str()); -} diff --git a/src/Cluster_ReadInfo.h b/src/Cluster_ReadInfo.h deleted file mode 100644 index 89e3414b5c..0000000000 --- a/src/Cluster_ReadInfo.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef INC_CLUSTER_READINFO_H -#define INC_CLUSTER_READINFO_H -#include "ClusterList.h" -/// Read in previous cluster run -class Cluster_ReadInfo : public ClusterList { - public: - Cluster_ReadInfo(); - static void Help(); - int SetupCluster(ArgList&); - void ClusteringInfo() const; - int Cluster(); -# ifdef TIMER - void Timing(double) const {} -# endif - void AddSievedFrames() { } - void ClusterResults(CpptrajFile&) const; - private: - std::string filename_; - std::string algorithm_; -}; -#endif diff --git a/src/Command.cpp b/src/Command.cpp index 42d7c724c0..4854391fc5 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -167,7 +167,6 @@ #include "Analysis_CrdFluct.h" #include "Analysis_RmsAvgCorr.h" #include "Analysis_Rms2d.h" -#include "Analysis_Clustering.h" #include "Analysis_RunningAvg.h" #include "Analysis_MeltCurve.h" #include "Analysis_Overlap.h" @@ -190,6 +189,7 @@ #include "Analysis_Multicurve.h" #include "Analysis_TI.h" #include "Analysis_ConstantPHStats.h" +#include "Analysis_Clustering.h" #include "Analysis_HausdorffDistance.h" #include "Analysis_Slope.h" #include "Analysis_EvalPlateau.h" diff --git a/src/DataFile.cpp b/src/DataFile.cpp index d7befd8462..4965c47b6c 100644 --- a/src/DataFile.cpp +++ b/src/DataFile.cpp @@ -21,13 +21,13 @@ #include "DataIO_VecTraj.h" #include "DataIO_XVG.h" #include "DataIO_CCP4.h" -#include "DataIO_Cmatrix.h" -#include "DataIO_NC_Cmatrix.h" #include "DataIO_CharmmRepLog.h" #include "DataIO_CharmmFastRep.h" #include "DataIO_CharmmOutput.h" #include "DataIO_Cpout.h" #include "DataIO_CharmmRtfPrm.h" +#include "DataIO_Cmatrix_Binary.h" +#include "DataIO_Cmatrix_NC.h" #include "DataIO_Peaks.h" // CONSTRUCTOR @@ -63,17 +63,17 @@ const FileTypes::AllocToken DataFile::DF_AllocArray[] = { { "Vector pseudo-traj", 0, DataIO_VecTraj::WriteHelp,DataIO_VecTraj::Alloc}, { "XVG file", 0, 0, DataIO_XVG::Alloc }, { "CCP4 file", 0, DataIO_CCP4::WriteHelp, DataIO_CCP4::Alloc }, - { "Cluster matrix file",0, 0, DataIO_Cmatrix::Alloc}, -# ifdef BINTRAJ - { "NetCDF Cluster matrix file", 0, 0, DataIO_NC_Cmatrix::Alloc}, -# else - { "NetCDF Cluster matrix file", 0, 0, 0 }, -# endif { "CHARMM REM log", DataIO_CharmmRepLog::ReadHelp, 0, DataIO_CharmmRepLog::Alloc}, { "CHARMM Fast REM log",0, 0, DataIO_CharmmFastRep::Alloc}, { "CHARMM Output", 0, 0, DataIO_CharmmOutput::Alloc}, { "Amber CPOUT", DataIO_Cpout::ReadHelp, DataIO_Cpout::WriteHelp, DataIO_Cpout::Alloc}, { "CHARMM RTF/PRM", 0, 0, DataIO_CharmmRtfPrm::Alloc }, + { "Pairwise Cache (binary)", 0, 0, DataIO_Cmatrix_Binary::Alloc }, +# ifdef BINTRAJ + { "Pairwise Cache (NetCDF)", 0, 0, DataIO_Cmatrix_NC::Alloc }, +# else + { "Pairwise Cache (NetCDF)", 0, 0, 0 }, +# endif { "Peaks", 0, 0, DataIO_Peaks::Alloc }, { "Unknown Data file", 0, 0, 0 } }; @@ -91,11 +91,11 @@ const FileTypes::KeyToken DataFile::DF_KeyArray[] = { { EVECS, "evecs", ".evecs" }, { XVG, "xvg", ".xvg" }, { CCP4, "ccp4", ".ccp4" }, - { CMATRIX, "cmatrix",".cmatrix" }, - { NCCMATRIX, "nccmatrix", ".nccmatrix" }, { CHARMMREPD, "charmmrepd",".exch" }, { CHARMMOUT, "charmmout", ".charmmout"}, { CHARMMRTFPRM, "charmmrtfprm", ".rtfprm"}, + { CMATRIX_BINARY,"cmatrix",".cmatrix" }, + { CMATRIX_NETCDF,"nccmatrix", ".nccmatrix" }, { PEAKS, "peaks", ".peaks" }, { UNKNOWN_DATA, 0, 0 } }; @@ -112,9 +112,9 @@ const FileTypes::KeyToken DataFile::DF_WriteKeyArray[] = { { EVECS, "evecs", ".evecs" }, { VECTRAJ, "vectraj",".vectraj" }, { CCP4, "ccp4", ".ccp4" }, - { CMATRIX, "cmatrix",".cmatrix" }, - { NCCMATRIX, "nccmatrix", ".nccmatrix" }, { CPOUT, "cpout", ".cpout" }, + { CMATRIX_BINARY,"cmatrix",".cmatrix" }, + { CMATRIX_NETCDF,"nccmatrix", ".nccmatrix" }, { CHARMMRTFPRM, "charmmrtfprm", ".prm" }, { PEAKS, "peaks", ".peaks" }, { UNKNOWN_DATA, 0, 0 } diff --git a/src/DataFile.h b/src/DataFile.h index 0517c00774..a550a03d92 100644 --- a/src/DataFile.h +++ b/src/DataFile.h @@ -16,8 +16,9 @@ class DataFile { /// Known data file formats. enum DataFormatType { DATAFILE=0, XMGRACE, GNUPLOT, XPLOR, OPENDX, REMLOG, MDOUT, EVECS, - VECTRAJ, XVG, CCP4, CMATRIX, NCCMATRIX, CHARMMREPD, CHARMMFASTREP, - CHARMMOUT, CPOUT, CHARMMRTFPRM, PEAKS, UNKNOWN_DATA + VECTRAJ, XVG, CCP4, CHARMMREPD, CHARMMFASTREP, + CHARMMOUT, CPOUT, CHARMMRTFPRM, CMATRIX_BINARY, CMATRIX_NETCDF, PEAKS, + UNKNOWN_DATA }; DataFile(); ~DataFile(); diff --git a/src/DataIO_Cmatrix.cpp b/src/DataIO_Cmatrix.cpp deleted file mode 100644 index 8f4ab96ad4..0000000000 --- a/src/DataIO_Cmatrix.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include "DataIO_Cmatrix.h" -#include "CpptrajStdio.h" - -// NOTES: -// Version 1: Add write of ignore array when reduced. Write nrows and -// and nelements as 8 byte integers. -// Version 2: Instead of nrows and nelements, write original nrows -// and actual nrows to easily determine if this is a reduced -// matrix. Also write sieve value. -// Version 2 Update: Read/write sieve value as signed, negative -// value is random sieve. Variable is same # -// of bytes so should be backwards-compatible. -const unsigned char DataIO_Cmatrix::Magic_[4] = {'C', 'T', 'M', 2}; - -// CONSTRUCTOR -DataIO_Cmatrix::DataIO_Cmatrix() -{ - SetValid( DataSet::CMATRIX ); -} - -bool DataIO_Cmatrix::ID_DataFormat(CpptrajFile& infile) { - unsigned char magic[4]; - if (infile.OpenFile()) return false; - infile.Read( magic, 4 ); - infile.CloseFile(); - return (magic[0]==Magic_[0] && magic[1]==Magic_[1] && magic[2]==Magic_[2]); -} - -// ----------------------------------------------------------------------------- -// DataIO_Cmatrix::ReadHelp() -void DataIO_Cmatrix::ReadHelp() { - -} - -// DataIO_Cmatrix::processReadArgs() -int DataIO_Cmatrix::processReadArgs(ArgList& argIn) { - - return 0; -} - -// DataIO_Cmatrix::ReadData() -int DataIO_Cmatrix::ReadData(FileName const& fname, - DataSetList& dsl, std::string const& dsname) -{ - // Allocate data set - MetaData md( dsname, MetaData::M_MATRIX ); - DataSet* ds = dsl.AddSet(DataSet::CMATRIX, md, "Cmatrix"); - if (ds == 0) return 1; - DataSet_Cmatrix_MEM& Mat = static_cast( *ds ); - return ReadCmatrix(fname, Mat); -} - -// DataIO_Cmatrix::ReadCmatrix() -int DataIO_Cmatrix::ReadCmatrix(FileName const& fname, DataSet_Cmatrix_MEM& Mat) { - unsigned char magic[4]; - CpptrajFile infile; - uint_8 ROWS, ELTS; - sint_8 SIEVE; - int sieve = 1; - size_t actual_nrows = 0; - // Open file for reading - if (infile.OpenRead(fname)) { - mprinterr("Error: Could not open '%s' for read.\n", fname.full()); - return 1; - } - // SANITY CHECK: Read and check magic byte - infile.Read( magic, 4 ); - if ( magic[0]!=Magic_[0] || magic[1]!=Magic_[1] || magic[2]!=Magic_[2] ) { - mprinterr("Error: File '%s' is not a Cpptraj Cluster Matrix file.\n", fname.full()); - return 1; - } - // Check version, read in nrows and nelements. - if (magic[3] == 0) { - int Ntemp = 0; - infile.Read( &Ntemp, sizeof(int) ); - ROWS = (uint_8)Ntemp; - actual_nrows = (size_t)ROWS; - infile.Read( &Ntemp, sizeof(int) ); - ELTS = (uint_8)Ntemp; - } else if (magic[3] == 1) { - infile.Read( &ROWS, sizeof(uint_8) ); - actual_nrows = (size_t)ROWS; - infile.Read( &ELTS, sizeof(uint_8) ); - } else if (magic[3] == 2) { - infile.Read( &ROWS, sizeof(uint_8) ); // V2: Original Nrows - infile.Read( &ELTS, sizeof(uint_8) ); // V2: Actual Nrows - actual_nrows = (size_t)ELTS; - infile.Read( &SIEVE, sizeof(sint_8) ); // V2: Sieve - sieve = (int)SIEVE; - } else { - mprinterr("Error: ClusterMatrix version %u is not recognized.\n", (unsigned int)magic[3]); - return 1; - } - // If number of rows is not what was expected, abort TODO reimplement somewhere else -/* - if (ROWS != (uint_8)sizeIn) { - mprinterr("Error: ClusterMatrix file %s has %lu rows, expected %i.\n", - fname.full(), ROWS, sizeIn); - return 1; - } -*/ - if (magic[3] == 0 || magic[3] == 1) { - // Version 0/1: Actual # of rows is not known yet. Check that the # elements - // in the file match the original # elements (i.e. matrix is not sieved). - // If it is sieved this is not supported. - uint_8 original_nelements = ( ROWS * (ROWS - 1UL) ) / 2UL; - if ( original_nelements != ELTS ) { - mprinterr("Error: Sieved data in ClusterMatrix file %s (version %u) not supported.\n", - fname.full(), (unsigned int)magic[3]); - return 1; - } - sieve = 1; - } - // Setup underlying TriangleMatrix for actual # of rows - if ( Mat.Allocate( DataSet::SizeArray(1,actual_nrows) ) ) return 1; - // Read in matrix elements - infile.Read( Mat.Ptr(), Mat.Size()*sizeof(float) ); - // If sieved, read in the sieve status array. 'T'=sieved, 'F'=not sieved - std::vector sieveStatus; - if (sieve != 1) { - mprintf("Warning: ClusterMatrix %s contains sieved data.\n", fname.full()); - sieveStatus.resize( ROWS ); // Original nrows - infile.Read( &sieveStatus[0], ROWS*sizeof(char) ); - } else - // No sieved frames. - sieveStatus.assign( ROWS, 'F' ); - // Set sieve status. - if (Mat.SetSieveFromArray(sieveStatus, sieve)) return 1; - - return 0; -} - -// ----------------------------------------------------------------------------- -// DataIO_Cmatrix::WriteHelp() -void DataIO_Cmatrix::WriteHelp() { - -} - -// DataIO_Cmatrix::processWriteArgs() -int DataIO_Cmatrix::processWriteArgs(ArgList &argIn) { - - return 0; -} - -// DataIO_Cmatrix::WriteData() -int DataIO_Cmatrix::WriteData(FileName const& fname, DataSetList const& SetList) -{ - if (SetList.empty()) return 1; - if (SetList.size() > 1) - mprintf("Warning: Multiple sets not yet supported for cluster matrix write.\n"); - DataSet_Cmatrix_MEM const& Mat = static_cast( *(*(SetList.begin())) ); - return WriteCmatrix( fname, Mat ); -} - -// DataIO_Cmatrix::WriteCmatrix() -int DataIO_Cmatrix::WriteCmatrix(FileName const& fname, DataSet_Cmatrix_MEM const& Mat) { - CpptrajFile outfile; - uint_8 ntemp; - // No stdout write allowed. - if (fname.empty()) { - mprinterr("Internal Error: DataIO_Cmatrix::WriteData() called with no filename.\n"); - return 1; - } - if (outfile.OpenWrite(fname)) { - mprinterr("Error: Could not open %s for write.\n", fname.full()); - return 1; - } - // Write magic byte - outfile.Write( Magic_, 4 ); - // Write original number of frames. - ntemp = (uint_8)Mat.OriginalNframes(); - outfile.Write( &ntemp, sizeof(uint_8) ); - // Write actual nrows - ntemp = (uint_8)Mat.Nrows(); - outfile.Write( &ntemp, sizeof(uint_8) ); - // Write out sieve value - sint_8 stemp = (sint_8)Mat.SieveValue(); - outfile.Write( &stemp, sizeof(sint_8) ); - // Write matrix elements - outfile.Write( Mat.Ptr(), Mat.Size()*sizeof(float) ); - // If this is a reduced matrix, write whether each frame was sieved (T) or not (F). - if (Mat.SieveType() != ClusterSieve::NONE) { - std::vector sieveStatus( Mat.OriginalNframes() ); - for (int idx = 0; idx != Mat.OriginalNframes(); idx++) - if (Mat.FrameWasSieved(idx)) - sieveStatus[idx] = 'T'; - else - sieveStatus[idx] = 'F'; - outfile.Write( &sieveStatus[0], Mat.OriginalNframes()*sizeof(char) ); - } - return 0; -} diff --git a/src/DataIO_Cmatrix_Binary.cpp b/src/DataIO_Cmatrix_Binary.cpp new file mode 100644 index 0000000000..9f4a211a72 --- /dev/null +++ b/src/DataIO_Cmatrix_Binary.cpp @@ -0,0 +1,99 @@ +#include "DataIO_Cmatrix_Binary.h" +#include "CpptrajStdio.h" +#include "Cluster/Cmatrix_Binary.h" + +using namespace Cpptraj; +using namespace Cluster; + +// CONSTRUCTOR +DataIO_Cmatrix_Binary::DataIO_Cmatrix_Binary() +{ + SetValid( DataSet::PMATRIX_MEM ); +} + +bool DataIO_Cmatrix_Binary::ID_DataFormat(CpptrajFile& infile) { + return Cmatrix_Binary::ID_Cmatrix( infile ); +} + +// ----------------------------------------------------------------------------- +// DataIO_Cmatrix_Binary::ReadHelp() +void DataIO_Cmatrix_Binary::ReadHelp() { + +} + +// DataIO_Cmatrix_Binary::processReadArgs() +int DataIO_Cmatrix_Binary::processReadArgs(ArgList& argIn) { + + return 0; +} + +// DataIO_Cmatrix_Binary::ReadData() +int DataIO_Cmatrix_Binary::ReadData(FileName const& fname, + DataSetList& dsl, std::string const& dsname) +{ + // Allocate data set + MetaData md( dsname, MetaData::M_MATRIX ); + DataSet* ds = dsl.AddSet(DataSet::PMATRIX_MEM, md ); + if (ds == 0) return 1; + DataSet_PairwiseCache_MEM& Mat = static_cast( *ds ); + return ReadCmatrix(fname, Mat); +} + +// DataIO_Cmatrix_Binary::ReadCmatrix() +int DataIO_Cmatrix_Binary::ReadCmatrix(FileName const& fname, DataSet_PairwiseCache_MEM& Mat) { + Cmatrix_Binary infile; + + if (infile.OpenCmatrixRead( fname )) return 1; + + // Setup underlying TriangleMatrix for actual # of rows + if ( Mat.Allocate( DataSet::SizeArray(1, infile.ActualNrows()) ) ) return 1; + // Allocate sieve status array if needed + char* sieveStatus = 0; + DataSet_PairwiseCache::StatusArray ssArray; // TODO just pass in char array instead of ptr? + if (infile.Sieve() != 1) { + ssArray.resize( infile.Ntotal() ); + sieveStatus = &ssArray[0]; + } else { + // All present + ssArray.assign( infile.Ntotal(), DataSet_PairwiseCache::PRESENT_ ); + } + // Read in matrix elements + if (infile.GetCmatrix( Mat.Ptr(), sieveStatus )) return 1; + + // Set sieve status. + if (Mat.SetupFromStatus(ssArray, infile.Sieve())) return 1; + + return 0; +} + +// ----------------------------------------------------------------------------- +// DataIO_Cmatrix_Binary::WriteHelp() +void DataIO_Cmatrix_Binary::WriteHelp() { + +} + +// DataIO_Cmatrix_Binary::processWriteArgs() +int DataIO_Cmatrix_Binary::processWriteArgs(ArgList &argIn) { + + return 0; +} + +// DataIO_Cmatrix_Binary::WriteData() +int DataIO_Cmatrix_Binary::WriteData(FileName const& fname, DataSetList const& SetList) +{ + if (SetList.empty()) return 1; + if (SetList.size() > 1) + mprintf("Warning: Multiple sets not yet supported for cluster matrix write.\n"); + DataSet_PairwiseCache_MEM const& Mat = + static_cast( *(*(SetList.begin())) ); + return WriteCmatrix( fname, Mat ); +} + +// DataIO_Cmatrix_Binary::WriteCmatrix() +int DataIO_Cmatrix_Binary::WriteCmatrix(FileName const& fname, + DataSet_PairwiseCache_MEM const& Mat) +{ + int err = Cmatrix_Binary::WriteCmatrix( fname, Mat.Ptr(), Mat.FrameToIdx(), + Mat.Nrows(), Mat.SieveVal() ); + return err; +} diff --git a/src/DataIO_Cmatrix.h b/src/DataIO_Cmatrix_Binary.h similarity index 50% rename from src/DataIO_Cmatrix.h rename to src/DataIO_Cmatrix_Binary.h index c1b832a151..0b3dbfafe6 100644 --- a/src/DataIO_Cmatrix.h +++ b/src/DataIO_Cmatrix_Binary.h @@ -1,12 +1,12 @@ -#ifndef INC_DATAIO_CMATRIX_H -#define INC_DATAIO_CMATRIX_H +#ifndef INC_DATAIO_CMATRIX_BINARY_H +#define INC_DATAIO_CMATRIX_BINARY_H #include "DataIO.h" -#include "DataSet_Cmatrix_MEM.h" +#include "DataSet_PairwiseCache_MEM.h" // TODO just pairwisecache /// Read/write cpptraj-format binary cluster pairwise distance matrix files. -class DataIO_Cmatrix : public DataIO { +class DataIO_Cmatrix_Binary : public DataIO { public: - DataIO_Cmatrix(); - static BaseIOtype* Alloc() { return (BaseIOtype*)new DataIO_Cmatrix(); } + DataIO_Cmatrix_Binary(); + static BaseIOtype* Alloc() { return (BaseIOtype*)new DataIO_Cmatrix_Binary(); } static void ReadHelp(); static void WriteHelp(); int processReadArgs(ArgList&); @@ -15,13 +15,8 @@ class DataIO_Cmatrix : public DataIO { int WriteData(FileName const&,DataSetList const&); bool ID_DataFormat(CpptrajFile&); // ------------------------------------------- - int ReadCmatrix(FileName const&, DataSet_Cmatrix_MEM&); - int WriteCmatrix(FileName const&, DataSet_Cmatrix_MEM const&); + int ReadCmatrix(FileName const&, DataSet_PairwiseCache_MEM&); + int WriteCmatrix(FileName const&, DataSet_PairwiseCache_MEM const&); private: - static const unsigned char Magic_[]; - /// For reading/writing 8 byte unsigned integers - typedef unsigned long long int uint_8; - /// For reading/writing 8 byte signed integers - typedef long long int sint_8; }; #endif diff --git a/src/DataIO_Cmatrix_NC.cpp b/src/DataIO_Cmatrix_NC.cpp new file mode 100644 index 0000000000..8e31b298fc --- /dev/null +++ b/src/DataIO_Cmatrix_NC.cpp @@ -0,0 +1,55 @@ +#ifdef BINTRAJ +#include "DataIO_Cmatrix_NC.h" +#include "DataSet_PairwiseCache_MEM.h" // TODO just pairwisecache +#include "CpptrajStdio.h" + +/// CONSTRUCTOR +DataIO_Cmatrix_NC::DataIO_Cmatrix_NC() { + SetValid( DataSet::PMATRIX_MEM ); +} + +// DataIO_Cmatrix_NC::ReadData() +int DataIO_Cmatrix_NC::ReadData(FileName const& fname, + DataSetList& dsl, std::string const& dsname) +{ + int sieve; + if (file_.OpenCmatrixRead(fname, sieve)) return 1; + + MetaData md( dsname ); + md.SetFileName( fname ); + DataSet* ds = dsl.AddSet( DataSet::PMATRIX_MEM, md ); + if (ds == 0) return 1; + DataSet_PairwiseCache_MEM& cmatrix = static_cast( *ds ); + // Allocate matrix for actual number of rows + if (cmatrix.Allocate( DataSet::SizeArray(1, file_.MatrixRows()) )) return 1; + // Get the sieve status array. + if (cmatrix.SetupFromStatus( file_.GetSieveStatus(), sieve )) return 1; + // Get the matrix + if (file_.GetCmatrix( cmatrix.Ptr() )) return 1; + file_.CloseCmatrix(); + + return 0; +} + +int DataIO_Cmatrix_NC::WriteData(FileName const& fname, DataSetList const& SetList) +{ + if (SetList.empty()) return 1; + if (SetList.size() > 1) + mprintf("Warning: Multiple sets not yet supported for cluster matrix write.\n"); + DataSet_PairwiseCache_MEM const& Mat = + static_cast( *(*(SetList.begin())) ); + // Create the file + if (file_.CreateCmatrix( fname, Mat.FrameToIdx().size(), Mat.Nrows(), Mat.SieveVal(), + Mat.MetricDescrip() )) + return 1; + // Write the matrix + if (file_.WriteCmatrix( Mat.Ptr() )) return 1; + // Write present frames + if (Mat.SieveVal() != 1) { + if (file_.WriteFramesArray( Mat.PresentFrames() )) return 1; + } + + file_.CloseCmatrix(); + return 0; +} +#endif /* BINTRAJ */ diff --git a/src/DataIO_NC_Cmatrix.h b/src/DataIO_Cmatrix_NC.h similarity index 51% rename from src/DataIO_NC_Cmatrix.h rename to src/DataIO_Cmatrix_NC.h index de5e31e038..a8ed093ffd 100644 --- a/src/DataIO_NC_Cmatrix.h +++ b/src/DataIO_Cmatrix_NC.h @@ -1,21 +1,25 @@ -#ifndef INC_DATAIO_NC_CMATRIX_H -#define INC_DATAIO_NC_CMATRIX_H +#ifndef INC_DATAIO_CMATRIX_NC_H +#define INC_DATAIO_CMATRIX_NC_H +#ifdef BINTRAJ #include "DataIO.h" -#include "NC_Cmatrix.h" +#include "Cluster/Cmatrix_NC.h" /// Read/write NetCDF pairwise matrix files. -class DataIO_NC_Cmatrix : public DataIO { +class DataIO_Cmatrix_NC : public DataIO { public: - DataIO_NC_Cmatrix(); - ~DataIO_NC_Cmatrix() { file_.CloseCmatrix(); } - static BaseIOtype* Alloc() { return (BaseIOtype*)new DataIO_NC_Cmatrix(); } + DataIO_Cmatrix_NC(); + ~DataIO_Cmatrix_NC() { file_.CloseCmatrix(); } + static BaseIOtype* Alloc() { return (BaseIOtype*)new DataIO_Cmatrix_NC(); } static void ReadHelp() {} static void WriteHelp() {} int processReadArgs(ArgList&) { return 0; } int ReadData(FileName const&,DataSetList&,std::string const&); int processWriteArgs(ArgList&) { return 0; } int WriteData(FileName const&,DataSetList const&); - bool ID_DataFormat(CpptrajFile& f) { return NC_Cmatrix::ID_Cmatrix(f.Filename()); } + bool ID_DataFormat(CpptrajFile& f) { + return Cpptraj::Cluster::Cmatrix_NC::ID_Cmatrix(f.Filename()); + } private: - NC_Cmatrix file_; + Cpptraj::Cluster::Cmatrix_NC file_; }; +#endif /* BINTRAJ */ #endif diff --git a/src/DataIO_NC_Cmatrix.cpp b/src/DataIO_NC_Cmatrix.cpp deleted file mode 100644 index d93f1b36ea..0000000000 --- a/src/DataIO_NC_Cmatrix.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "DataIO_NC_Cmatrix.h" -#include "DataSet_Cmatrix_MEM.h" -#include "CpptrajStdio.h" - -/// CONSTRUCTOR -DataIO_NC_Cmatrix::DataIO_NC_Cmatrix() { - SetValid( DataSet::CMATRIX ); -} - -// DataIO_NC_Cmatrix::ReadData() -int DataIO_NC_Cmatrix::ReadData(FileName const& fname, - DataSetList& dsl, std::string const& dsname) -{ - int sieve; - if (file_.OpenCmatrixRead(fname, sieve)) return 1; - - MetaData md( dsname ); - md.SetFileName( fname ); - DataSet* ds = dsl.AddSet( DataSet::CMATRIX, md ); - if (ds == 0) return 1; - DataSet_Cmatrix_MEM& cmatrix = static_cast( *ds ); - // Allocate matrix for actual number of rows - if (cmatrix.Allocate( DataSet::SizeArray(1, file_.MatrixRows()) )) return 1; - // Get the sieve status array. - if (cmatrix.SetSieveFromArray( file_.GetSieveStatus(), sieve )) return 1; - // Get the matrix - if (file_.GetCmatrix( cmatrix.Ptr() )) return 1; - file_.CloseCmatrix(); - - return 0; -} - -int DataIO_NC_Cmatrix::WriteData(FileName const& fname, DataSetList const& SetList) -{ - if (SetList.empty()) return 1; - if (SetList.size() > 1) - mprintf("Warning: Multiple sets not yet supported for cluster matrix write.\n"); - DataSet_Cmatrix_MEM const& Mat = static_cast( *(*(SetList.begin())) ); - // Create the file - if (file_.CreateCmatrix( fname, Mat.OriginalNframes(), Mat.Nrows(), Mat.SieveValue(), - Mat.MetricDescription() )) - return 1; - // Write the matrix - if (file_.WriteCmatrix( Mat.Ptr() )) return 1; - // Write sieved frames - if (Mat.SieveType() != ClusterSieve::NONE) { - if (file_.WriteFramesArray( Mat.FramesToCluster() )) return 1; - } - - file_.CloseCmatrix(); - return 0; -} diff --git a/src/DataIO_Std.cpp b/src/DataIO_Std.cpp index 28af10dd67..023b3d3169 100644 --- a/src/DataIO_Std.cpp +++ b/src/DataIO_Std.cpp @@ -16,11 +16,11 @@ #include "DataSet_string.h" // For reading TODO remove dependency? #include "DataSet_Vector.h" // For reading TODO remove dependency? #include "DataSet_Mat3x3.h" // For reading TODO remove dependency? +#include "DataSet_PairwiseCache_MEM.h" // For reading #include "DataSet_2D.h" #include "DataSet_MatrixFlt.h" #include "DataSet_MatrixDbl.h" #include "DataSet_3D.h" -#include "DataSet_Cmatrix_MEM.h" // CONSTRUCTOR DataIO_Std::DataIO_Std() : @@ -409,9 +409,9 @@ int DataIO_Std::ReadCmatrix(FileName const& fname, DataSetList& datasetlist, std::string const& dsname) { // Allocate output data set - DataSet* ds = datasetlist.AddSet( DataSet::CMATRIX, dsname ); + DataSet* ds = datasetlist.AddSet( DataSet::PMATRIX_MEM, dsname ); if (ds == 0) return 1; - DataSet_Cmatrix_MEM& Mat = static_cast( *ds ); + DataSet_PairwiseCache_MEM& Mat = static_cast( *ds ); // Buffer file BufferedLine buffer; if (buffer.OpenFileRead( fname )) return 1; @@ -421,9 +421,9 @@ int DataIO_Std::ReadCmatrix(FileName const& fname, header.SetList(ptr+1, SEPARATORS ); int nframes = header.getKeyInt("nframes", -1); // Need to keep track of frame indices so we can check for sieving. - std::vector sieveStatus; + DataSet_PairwiseCache::StatusArray sieveStatus; if (nframes > 0) - sieveStatus.assign(nframes, 'T'); + sieveStatus.assign(nframes, DataSet_PairwiseCache::ABSENT_); // Keep track of matrix values. std::vector Vals; // Read file @@ -435,16 +435,16 @@ int DataIO_Std::ReadCmatrix(FileName const& fname, if (checkSieve) { sscanf(ptr, "%i %i %f", &f1, &f2, &val); if (f2 > (int)sieveStatus.size()) - sieveStatus.resize(f2, 'T'); + sieveStatus.resize(f2, DataSet_PairwiseCache::ABSENT_); if (firstf1 == -1) { // First values. - sieveStatus[f1-1] = 'F'; - sieveStatus[f2-1] = 'F'; + sieveStatus[f1-1] = DataSet_PairwiseCache::PRESENT_; + sieveStatus[f2-1] = DataSet_PairwiseCache::PRESENT_; firstf1 = f1; } else if (f1 > firstf1) { checkSieve = false; } else { - sieveStatus[f2-1] = 'F'; + sieveStatus[f2-1] = DataSet_PairwiseCache::PRESENT_; } } else { sscanf(ptr, "%*i %*i %f", &val); @@ -452,16 +452,16 @@ int DataIO_Std::ReadCmatrix(FileName const& fname, Vals.push_back( val ); } // DEBUG - //mprintf("Sieved array:\n"); - //for (unsigned int i = 0; i < sieveStatus.size(); i++) - // mprintf("\t%6u %c\n", i+1, sieveStatus[i]); + mprintf("Sieved array:\n"); + for (unsigned int i = 0; i < sieveStatus.size(); i++) + mprintf("\t%6u %c\n", i+1, sieveStatus[i]); // Try to determine if sieve is random or not. int sieveDelta = 1; f1 = -1; f2 = -1; int actual_nrows = 0; for (int i = 0; i < (int)sieveStatus.size(); i++) { - if (sieveStatus[i] == 'F') { + if (sieveStatus[i] == DataSet_PairwiseCache::PRESENT_) { actual_nrows++; if (sieveDelta != -2) { if (f1 == -1) { @@ -501,7 +501,8 @@ int DataIO_Std::ReadCmatrix(FileName const& fname, // Save cluster matrix if (Mat.Allocate( DataSet::SizeArray(1, actual_nrows) )) return 1; std::copy( Vals.begin(), Vals.end(), Mat.Ptr() ); - Mat.SetSieveFromArray(sieveStatus, sieveDelta); + // TODO may need to pass in actual sieve here + Mat.SetupFromStatus(sieveStatus, sieveDelta); return 0; } @@ -1155,7 +1156,7 @@ int DataIO_Std::WriteData(FileName const& fname, DataSetList const& SetList) CpptrajFile file; if (file.OpenWrite( fname )) return 1; // Base write type off first data set dimension FIXME - if (SetList[0]->Group() == DataSet::CLUSTERMATRIX) { + if (SetList[0]->Group() == DataSet::PWCACHE) { // Special case of 2D - may have sieved frames. err = WriteCmatrix(file, SetList); } else if (SetList[0]->Ndim() == 1) { @@ -1179,20 +1180,20 @@ int DataIO_Std::WriteData(FileName const& fname, DataSetList const& SetList) int DataIO_Std::WriteCmatrix(CpptrajFile& file, DataSetList const& Sets) { for (DataSetList::const_iterator ds = Sets.begin(); ds != Sets.end(); ++ds) { - if ( (*ds)->Group() != DataSet::CLUSTERMATRIX) { + if ( (*ds)->Group() != DataSet::PWCACHE) { mprinterr("Error: Write of cluster matrix and other sets to same file not supported.\n" "Error: Skipping '%s'\n", (*ds)->legend()); continue; } - DataSet_Cmatrix const& cm = static_cast( *(*ds) ); - int nrows = cm.OriginalNframes(); + DataSet_PairwiseCache const& cm = static_cast( *(*ds) ); + int nrows = cm.Nrows(); int col_width = std::max(3, DigitWidth( nrows ) + 1); int dat_width = std::max(cm.Format().Width(), (int)cm.Meta().Legend().size()) + 1; WriteNameToBuffer(file, "F1", col_width, true); WriteNameToBuffer(file, "F2", col_width, false); WriteNameToBuffer(file, cm.Meta().Legend(), dat_width, false); - if (cm.SieveType() != ClusterSieve::NONE) - file.Printf(" nframes %i", cm.OriginalNframes()); + if (cm.SieveVal() != 1) + file.Printf(" nframes %i", nrows); file.Printf("\n"); TextFormat col_fmt(TextFormat::INTEGER, col_width); TextFormat dat_fmt = cm.Format(); @@ -1200,13 +1201,13 @@ int DataIO_Std::WriteCmatrix(CpptrajFile& file, DataSetList const& Sets) { dat_fmt.SetFormatWidth( dat_width ); std::string total_fmt = col_fmt.Fmt() + col_fmt.Fmt() + dat_fmt.Fmt() + "\n"; //mprintf("DEBUG: format '%s'\n", total_fmt.c_str()); - ClusterSieve::SievedFrames const& frames = cm.FramesToCluster(); + DataSet_PairwiseCache::Cframes frames = cm.PresentFrames(); int ntotal = (int)frames.size(); for (int idx1 = 0; idx1 != ntotal; idx1++) { int row = frames[idx1]; for (int idx2 = idx1 + 1; idx2 != ntotal; idx2++) { int col = frames[idx2]; - file.Printf(total_fmt.c_str(), row+1, col+1, cm.GetFdist(col, row)); + file.Printf(total_fmt.c_str(), row+1, col+1, cm.CachedDistance(idx1, idx2)); } } } diff --git a/src/DataSet.cpp b/src/DataSet.cpp index 8ab51de526..31a1dbca14 100644 --- a/src/DataSet.cpp +++ b/src/DataSet.cpp @@ -22,13 +22,12 @@ const char* DataSet::Descriptions_[] = { "reference", // REF_FRAME "3x3 matrices", // MAT3X3 "topology", // TOPOLOGY - "cluster matrix", // CMATRIX - "cluster matrix (no memory)", // CMATRIX_NOMEM - "cluster matrix (disk)", // CMATRIX_DISK "pH", // PH "pH REMD (explicit)", // PH_EXPL "pH REMD (implicit)", // PH_IMPL "parameters", // PARAMETERS + "pairwise matrix (mem)", // PMATRIX_MEM + "pairwise matrix (NetCDF)", // PMATRIX_NC "tensor", // TENSOR "string variable", // STRINGVAR "vector with scalar", // VECTOR_SCALAR diff --git a/src/DataSet.h b/src/DataSet.h index 4a411e930b..966364f522 100644 --- a/src/DataSet.h +++ b/src/DataSet.h @@ -27,12 +27,12 @@ class DataSet { enum DataType { UNKNOWN_DATA=0, DOUBLE, FLOAT, INTEGER, STRING, MATRIX_DBL, MATRIX_FLT, COORDS, VECTOR, MODES, GRID_FLT, GRID_DBL, REMLOG, XYMESH, TRAJ, REF_FRAME, - MAT3X3, TOPOLOGY, CMATRIX, CMATRIX_NOMEM, CMATRIX_DISK, PH, PH_EXPL, PH_IMPL, - PARAMETERS, TENSOR, STRINGVAR, VECTOR_SCALAR, UNSIGNED_INTEGER + MAT3X3, TOPOLOGY, PH, PH_EXPL, PH_IMPL, + PARAMETERS, PMATRIX_MEM, PMATRIX_NC, TENSOR, STRINGVAR, VECTOR_SCALAR, UNSIGNED_INTEGER }; /// Group DataSet belongs to. enum DataGroup { - GENERIC=0, SCALAR_1D, MATRIX_2D, GRID_3D, COORDINATES, CLUSTERMATRIX, PHREMD, VECTOR_1D + GENERIC=0, SCALAR_1D, MATRIX_2D, GRID_3D, COORDINATES, PHREMD, PWCACHE, VECTOR_1D }; DataSet(); @@ -130,8 +130,10 @@ class DataSet { return *first < *second; } }; - /// \return Text description based on DataType + /// \return Text description based on given DataType static const char* description(DataType t) { return Descriptions_[t]; } + /// \return Text description based on current DataType + const char* description() const { return Descriptions_[dType_]; } protected: TextFormat format_; ///< Text output data format. private: diff --git a/src/DataSetList.cpp b/src/DataSetList.cpp index 776a78c4fb..af0b2f162f 100644 --- a/src/DataSetList.cpp +++ b/src/DataSetList.cpp @@ -24,13 +24,12 @@ #include "DataSet_Mat3x3.h" #include "DataSet_Topology.h" #include "DataSet_GridDbl.h" -#include "DataSet_Cmatrix_MEM.h" -#include "DataSet_Cmatrix_NOMEM.h" -#include "DataSet_Cmatrix_DISK.h" #include "DataSet_pH.h" #include "DataSet_PHREMD_Explicit.h" #include "DataSet_PHREMD_Implicit.h" #include "DataSet_Parameters.h" +#include "DataSet_PairwiseCache_MEM.h" +#include "DataSet_PairwiseCache_NC.h" #include "DataSet_Tensor.h" #include "DataSet_StringVar.h" #include "DataSet_Vector_Scalar.h" @@ -75,13 +74,20 @@ DataSet* DataSetList::NewSet(DataSet::DataType typeIn) { case DataSet::REF_FRAME : ds = DataSet_Coords_REF::Alloc(); break; case DataSet::MAT3X3 : ds = DataSet_Mat3x3::Alloc(); break; case DataSet::TOPOLOGY : ds = DataSet_Topology::Alloc(); break; - case DataSet::CMATRIX : ds = DataSet_Cmatrix_MEM::Alloc(); break; - case DataSet::CMATRIX_NOMEM : ds = DataSet_Cmatrix_NOMEM::Alloc(); break; - case DataSet::CMATRIX_DISK : ds = DataSet_Cmatrix_DISK::Alloc(); break; case DataSet::PH : ds = DataSet_pH::Alloc(); break; case DataSet::PH_EXPL : ds = DataSet_PHREMD_Explicit::Alloc(); break; case DataSet::PH_IMPL : ds = DataSet_PHREMD_Implicit::Alloc(); break; case DataSet::PARAMETERS : ds = DataSet_Parameters::Alloc(); break; + // TODO useDiskCache + case DataSet::PMATRIX_MEM : ds = DataSet_PairwiseCache_MEM::Alloc(); break; + case DataSet::PMATRIX_NC : +# ifdef BINTRAJ + ds = DataSet_PairwiseCache_NC::Alloc(); +# else + mprinterr("Error: NetCDF pairwise disk cache requires NetCDF.\n"); + ds = 0; +# endif + break; case DataSet::TENSOR : ds = DataSet_Tensor::Alloc(); break; case DataSet::STRINGVAR : ds = DataSet_StringVar::Alloc(); break; case DataSet::VECTOR_SCALAR : ds = DataSet_Vector_Scalar::Alloc(); break; @@ -422,12 +428,14 @@ DataSet* DataSetList::AddSet( DataSet::DataType inType, MetaData const& metaIn, return AddSet( inType, meta ); } -/** Add a DataSet of specified type, set it up and return pointer to it. +/** Allocate a DataSet of specified type, set it up and return pointer to it. + * It will not be added to the list. * \param inType type of DataSet to add. * \param metaIn DataSet MetaData. * \return pointer to successfully set-up DataSet or 0 if error. */ -DataSet* DataSetList::AddSet(DataSet::DataType inType, MetaData const& metaIn) +DataSet* DataSetList::AllocateSet(DataSet::DataType inType, MetaData const& metaIn) +const { // TODO Always generate default name if empty? # ifdef TIMER time_total_.Start(); @@ -482,13 +490,29 @@ DataSet* DataSetList::AddSet(DataSet::DataType inType, MetaData const& metaIn) # endif # ifdef TIMER time_setup_.Stop(); - time_push_.Start(); # endif - Push_Back(DS); -# ifdef TIMER - time_push_.Stop(); -# endif - //fprintf(stderr,"ADDED dataset %s\n",dsetName); + //fprintf(stderr,"ALLOCATED dataset %s\n",dsetName); + return DS; +} + +/** Add a DataSet of specified type, set it up and return pointer to it. + * \param inType type of DataSet to add. + * \param metaIn DataSet MetaData. + * \return pointer to successfully set-up DataSet or 0 if error. + */ +DataSet* DataSetList::AddSet(DataSet::DataType inType, MetaData const& metaIn) +{ + DataSet* DS = AllocateSet(inType, metaIn); + if (DS != 0) { +# ifdef TIMER + time_push_.Start(); +# endif + Push_Back(DS); +# ifdef TIMER + time_push_.Stop(); +# endif + //fprintf(stderr,"ADDED dataset %s\n",dsetName); + } return DS; } diff --git a/src/DataSetList.h b/src/DataSetList.h index d3756d05f9..8fb262f986 100644 --- a/src/DataSetList.h +++ b/src/DataSetList.h @@ -108,6 +108,8 @@ class DataSetList { DataSet* AddSet_NoCheck(DataSet::DataType, MetaData const&); /// Add an already set up DataSet to list; memory for DataSet will be freed. int AddSet( DataSet* ); + /// Allocate DataSet but do not add to the list + DataSet* AllocateSet(DataSet::DataType, MetaData const&) const; /// Add new sets or append to existing ones. int AddOrAppendSets(std::string const&, Darray const&, DataListType const&); /// Add a copy of the DataSet to the list; memory for DataSet will not be freed. diff --git a/src/DataSet_Cmatrix.cpp b/src/DataSet_Cmatrix.cpp deleted file mode 100644 index 3f26e9d4a4..0000000000 --- a/src/DataSet_Cmatrix.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "DataSet_Cmatrix.h" -#include "CpptrajStdio.h" - -void DataSet_Cmatrix::PrintElements() const { - // NOTE: Matrix is square upper triangle, Nrows == Ncols - for (unsigned int row = 0; row != Nrows(); row++) - for (unsigned int col = row + 1; col != Nrows(); col++) - mprintf("\t%u %u %f\n", row+1, col+1, GetFdist(col, row)); -} - -/** Set up sieving info as necessary and set up cluster based on actual - * number of frames to be clustered. - */ -int DataSet_Cmatrix::SetupWithSieve(ClusterDist* CdistIn, size_t sizeIn, int sieveIn, int iseed) -{ - if (CdistIn == 0) { - mprinterr("Internal Error: DataSet_Cmatrix::SetupWithSieve called with empty ClusterDist.\n"); - return 1; - } - metricDescription_.assign( CdistIn->Description() ); - if (sievedFrames_.SetSieve( sieveIn, sizeIn, iseed )) return 1; - if (AllocateCmatrix( sievedFrames_.ActualNframes() )) return 1; - if (SetCdist(CdistIn)) return 1; - if (sievedFrames_.Type() != ClusterSieve::NONE) - mprintf("\tPair-wise matrix set up with sieve, %zu frames, %i sieved frames.\n", - sievedFrames_.MaxFrames(), sievedFrames_.ActualNframes()); - else - mprintf("\tPair-wise matrix set up, %zu frames\n", sizeIn); - return 0; -} - -/** Set up sieve info from an array that contains 'T' if the frame was sieved - * out and 'F' otherwise. - */ -int DataSet_Cmatrix::SetSieveFromArray(std::vector const& sieveStatus, int sieveIn) -{ - if (sieveStatus.empty()) return 1; - // Setup sieve class - if (sievedFrames_.SetSieve( sieveIn, sieveStatus )) { - mprinterr("Error: Could not set sieve from cluster matrix file.\n"); - return 1; - } - mprintf("\tSet up %s: %zu original frames, %u actual frames, %zu elements", - legend(), sievedFrames_.MaxFrames(), sievedFrames_.ActualNframes(), Nelements()); - if (sievedFrames_.Type() == ClusterSieve::REGULAR) - mprintf(", sieve= %i.\n", sievedFrames_.Sieve()); - else if (sievedFrames_.Type() == ClusterSieve::RANDOM) - mprintf(", random sieve.\n"); - else - mprintf(".\n"); - return 0; -} diff --git a/src/DataSet_Cmatrix.h b/src/DataSet_Cmatrix.h deleted file mode 100644 index fe17833df7..0000000000 --- a/src/DataSet_Cmatrix.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef INC_DATASET_CMATRIX_H -#define INC_DATASET_CMATRIX_H -#include "DataSet.h" -#include "ClusterSieve.h" -#include "ClusterDist.h" -/// Base class for pairwise distance matrices for clustering. -/** This matrix allows for sieving, i.e. it may hold less actual data than - * the original size would warrant. For example, if there were originally - * 10 rows of data the matrix would contain (10*9)/2 = 45 elements. However, - * if every other frame is sieved (i.e. sieve 2) we really only need info - * for (5*4)/2 = 10 elements; in this case we need to map original indices - * to actual indices, which is what the ClusterSieve class is for. - */ -class DataSet_Cmatrix : public DataSet { - public: - DataSet_Cmatrix() {} - DataSet_Cmatrix(DataType t) : DataSet(t, CLUSTERMATRIX, - TextFormat(TextFormat::DOUBLE, 12, 4), 2) {} - virtual ~DataSet_Cmatrix() {} - // ----- DataSet functions ------------------- - // NOTE: Disabled for all DataSet_Cmatrix sets - void Add(size_t, const void*) {} - int Append(DataSet*) { return 1; } -# ifdef MPI - int Sync(size_t, std::vector const&, Parallel::Comm const&) { return 1; } -# endif - // ----- Cmatrix functions ------------------- - /// \return Distance between given frames (indexed by sievedFrames). - virtual double GetFdist(int, int) const = 0; - /// Set element at column/row to given value - virtual void SetElement(int, int, double) = 0; - /// \return Actual number of elements in matrix - virtual size_t Nelements() const = 0; - /// \return size used by matrix in bytes - virtual size_t DataSize() const = 0; - /// \return Actual number of rows in the matrix. - virtual size_t Nrows() const = 0; - /// \return Element at given index. - virtual double GetElement(unsigned int) const = 0; - /// \return true if matrix needs setup - virtual bool NeedsSetup() const = 0; - /// \return true if matrix needs calculation - virtual bool NeedsCalc() const = 0; - /// Indicate that no more distances will be added to matrix. - virtual void Complete() = 0; - // ----- Sieved frames functions ------------- - /// \return An array containing frame numbers that have not been sieved out. - ClusterSieve::SievedFrames const& FramesToCluster() const { return sievedFrames_.Frames(); } - /// \return Sieve value - int SieveValue() const { return sievedFrames_.Sieve(); } - /// \return Sieve type - ClusterSieve::SieveType SieveType() const { return sievedFrames_.Type(); } - /// \return Original number of frames before sieving. - int OriginalNframes() const { return sievedFrames_.MaxFrames(); } - /// \return true if frame was sieved out. - bool FrameWasSieved(int f) const { return (sievedFrames_.FrameToIdx(f) == -1); } - // ------------------------------------------- - /// Allocate matrix and sieve info for given size and sieve - int SetupWithSieve(ClusterDist*, size_t, int, int); - /// Allocate sieve info from given array. - int SetSieveFromArray(std::vector const&, int); - /// Print matrix elements to STDOUT - void PrintElements() const; - /// \return Description of distance metric used to calc matrix - std::string const& MetricDescription() const { return metricDescription_; } - protected: - virtual int AllocateCmatrix(size_t) = 0; - virtual int SetCdist(ClusterDist*) = 0; - ClusterSieve sievedFrames_; ///< Hold info on frames actually being processed. TODO make private - private: - std::string metricDescription_; ///< Hold description of distance metric used to calc matrix -}; -#endif diff --git a/src/DataSet_Cmatrix_DISK.cpp b/src/DataSet_Cmatrix_DISK.cpp deleted file mode 100644 index a9cbf50c8b..0000000000 --- a/src/DataSet_Cmatrix_DISK.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "DataSet_Cmatrix_DISK.h" -#include "CpptrajStdio.h" -#include "StringRoutines.h" // ByteString - -int DataSet_Cmatrix_DISK::AllocateCmatrix(size_t sizeIn) { - if (Meta().Fname().empty()) { - mprinterr("Internal Error: Cluster matrix file name not set.\n"); - return 1; - } - mprintf("\tPairwise cache file: '%s'\n", Meta().Fname().full()); - mprintf("\tEstimated pair-wise matrix disk usage: > %s\n", - ByteString( ((sizeIn*(sizeIn-1))/2)*sizeof(float), BYTE_DECIMAL).c_str()); - if (file_.CreateCmatrix(Meta().Fname(), sievedFrames_.MaxFrames(), sizeIn, - sievedFrames_.Sieve(), MetricDescription())) - return 1; - // Write actual frames array if necessary - if (sievedFrames_.Type() != ClusterSieve::NONE) { - if (file_.WriteFramesArray( sievedFrames_.Frames() )) - return 1; - } - // Reopen in SHARE mode for random access - if (file_.ReopenSharedWrite( Meta().Fname() )) return 1; - return 0; -} diff --git a/src/DataSet_Cmatrix_DISK.h b/src/DataSet_Cmatrix_DISK.h deleted file mode 100644 index f6c6c5406b..0000000000 --- a/src/DataSet_Cmatrix_DISK.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef INC_DATASET_CMATRIX_DISK_H -#define INC_DATASET_CMATRIX_DISK_H -#include "DataSet_Cmatrix.h" -#include "NC_Cmatrix.h" -/// Used to hold pairwise distance matrix for clustering on disk. -class DataSet_Cmatrix_DISK : public DataSet_Cmatrix { - public: - DataSet_Cmatrix_DISK() : DataSet_Cmatrix(CMATRIX_DISK) {} - static DataSet* Alloc() { return (DataSet*)new DataSet_Cmatrix_DISK(); } - // ----- DataSet functions ------------------- - size_t Size() const { return file_.MatrixSize(); } - void Info() const { return; } - void WriteBuffer(CpptrajFile&, SizeArray const&) const {} - int Allocate(SizeArray const&) { return 0; } - /// \return Size in bytes of set - size_t MemUsageInBytes() const { return 0; } - // ----- Cmatrix functions ------------------- - /// \return an element indexed by sievedFrames. - inline double GetFdist(int, int) const; - /// Set element at column/row to given value - void SetElement(int x, int y, double val) { file_.WriteCmatrixElement(x, y, val); } - /// \return Actual number of elements in matrix - size_t Nelements() const { return file_.MatrixSize(); } - /// \return size used by matrix in bytes - size_t DataSize() const { return sievedFrames_.DataSize(); } - /// \return Actual number of rows in the matrix - size_t Nrows() const { return file_.MatrixRows(); } - /// \return Element at given index. - double GetElement(unsigned int idx) const { return file_.GetCmatrixElement(idx); } - /// \return true if matrix needs setup - bool NeedsSetup() const { return (file_.MatrixSize() < 1); } - /// \return true if matrix needs calculation - bool NeedsCalc() const { return true; } - /// No more distances will be added; flush to disk - void Complete() { file_.Sync(); } - protected: - int AllocateCmatrix(size_t); - int SetCdist(ClusterDist*) { return 0; } - private: - NC_Cmatrix file_; -}; -// ----- Inline functions ------------------------------------------------------ -double DataSet_Cmatrix_DISK::GetFdist(int x, int y) const { - return file_.GetCmatrixElement( sievedFrames_.FrameToIdx(x), - sievedFrames_.FrameToIdx(y) ); -} -#endif diff --git a/src/DataSet_Cmatrix_MEM.cpp b/src/DataSet_Cmatrix_MEM.cpp deleted file mode 100644 index 9c69053308..0000000000 --- a/src/DataSet_Cmatrix_MEM.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "DataSet_Cmatrix_MEM.h" -#include "CpptrajStdio.h" -#include "StringRoutines.h" // ByteString - -void DataSet_Cmatrix_MEM::WriteBuffer(CpptrajFile& outfile, SizeArray const& pIn) const { - size_t x = (size_t)pIn[0]; - size_t y = (size_t)pIn[1]; - if ( x >= Mat_.Ncols() || y >= Mat_.Nrows() ) - outfile.Printf(format_.fmt(), 0.0); - else - outfile.Printf(format_.fmt(), Mat_.element(x,y)); -} - -int DataSet_Cmatrix_MEM::Allocate(SizeArray const& sizeIn) { - int err = 0; - if (!sizeIn.empty()) { - // Sanity check. - if (sizeIn.size() > 1 && sizeIn[1] != sizeIn[0]) - mprintf("Warning: DataSet_Cmatrix dimensions must be equal (%zu != %zu)\n" - "Warning: Matrix will be %zu x %zu upper triangle\n", - sizeIn[0], sizeIn[1], sizeIn[0], sizeIn[0]); - err = Mat_.resize(0, sizeIn[0]); // Upper triangle - } else - Mat_.clear(); - return err; -} - -// ----------------------------------------------------------------------------- -// DataSet_Cmatrix_MEM::AllocateCmatrix() -int DataSet_Cmatrix_MEM::AllocateCmatrix(size_t sizeIn) -{ - // Set up underlying TriangleMatrix for given number of frames. - mprintf("\tEstimated pair-wise matrix memory usage: > %s\n", - ByteString(Mat_.sizeInBytes( 0L, sizeIn ), BYTE_DECIMAL).c_str()); - try { Mat_.resize( 0L, sizeIn ); } - catch (const std::bad_alloc&) { - mprinterr("Error: Not enough memory to allocate pair-wise matrix.\n" - "Error: Consider using the 'sieve' keyword to reduce memory usage.\n"); - return 1; - } - return 0; -} - -// DataSet_Cmatrix_MEM::DataSize() -size_t DataSet_Cmatrix_MEM::DataSize() const { - return ( Mat_.DataSize() + sievedFrames_.DataSize() ); -} diff --git a/src/DataSet_Cmatrix_MEM.h b/src/DataSet_Cmatrix_MEM.h deleted file mode 100644 index 34c23db56d..0000000000 --- a/src/DataSet_Cmatrix_MEM.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef INC_DATASET_CMATRIX_MEM_H -#define INC_DATASET_CMATRIX_MEM_H -#include "DataSet_Cmatrix.h" -#include "Matrix.h" -/// Used to hold pairwise distance matrix for clustering in memory. -class DataSet_Cmatrix_MEM : public DataSet_Cmatrix { - public: - DataSet_Cmatrix_MEM() : DataSet_Cmatrix(CMATRIX) {} - static DataSet* Alloc() { return (DataSet*)new DataSet_Cmatrix_MEM(); } - /// Access internal matrix pointer to interface with file IO - float* Ptr() { return Mat_.Ptr(); } - float const* Ptr() const { return Mat_.Ptr(); } - // ----- DataSet functions ------------------- - size_t Size() const { return Mat_.size(); } - void Info() const { return; } - void WriteBuffer(CpptrajFile&, SizeArray const&) const; - int Allocate(SizeArray const&); - /// \return Size in bytes of set - size_t MemUsageInBytes() const { return Mat_.DataSize(); } - // ----- Cmatrix functions ------------------- - /// \return an element indexed by sievedFrames. - inline double GetFdist(int, int) const; - /// Set element at column/row to given value - void SetElement(int col, int row, double val) { Mat_.setElement(col, row, val); } - /// \return Actual number of elements in matrix - size_t Nelements() const { return Mat_.size(); } - /// \return size used by matrix in bytes - size_t DataSize() const; - /// \return Actual number of rows in the matrix - size_t Nrows() const { return Mat_.Nrows(); } - /// \return Element at given index. - double GetElement(unsigned int idx) const { return Mat_[idx]; } - /// \return true if matrix needs setup - bool NeedsSetup() const { return (Mat_.size() < 1); } - /// \return true if matrix needs calculation - bool NeedsCalc() const { return true; } - /// Indicate that no more distances will be added to matrix. - void Complete() {} - protected: - int AllocateCmatrix(size_t); - int SetCdist(ClusterDist*) { return 0; } - private: - Matrix Mat_; -}; -// ----- Inline functions ------------------------------------------------------ -double DataSet_Cmatrix_MEM::GetFdist(int col, int row) const { - // row and col are based on original; convert to reduced - // FIXME: This assumes GetFdist will never be called for a sieved frame. - return Mat_.element(sievedFrames_.FrameToIdx(col), - sievedFrames_.FrameToIdx(row)); -} -#endif diff --git a/src/DataSet_Cmatrix_NOMEM.cpp b/src/DataSet_Cmatrix_NOMEM.cpp deleted file mode 100644 index e88846854e..0000000000 --- a/src/DataSet_Cmatrix_NOMEM.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include // std::min, std::max -#include "DataSet_Cmatrix_NOMEM.h" - -DataSet_Cmatrix_NOMEM::~DataSet_Cmatrix_NOMEM() { - if (cdist_ != 0) delete cdist_; -} - -void DataSet_Cmatrix_NOMEM::WriteBuffer(CpptrajFile& outfile, SizeArray const& pIn) const { - int xidx = (int)std::min(pIn[0], pIn[1]); - int yidx = (int)std::max(pIn[0], pIn[1]); - if ( xidx >= sievedFrames_.ActualNframes() || yidx >= sievedFrames_.ActualNframes() ) - outfile.Printf(format_.fmt(), 0.0); - else - outfile.Printf(format_.fmt(), cdist_->FrameDist( sievedFrames_.IdxToFrame(yidx), - sievedFrames_.IdxToFrame(xidx) )); -} - -int DataSet_Cmatrix_NOMEM::SetCdist(ClusterDist* cdistIn) -{ - if (cdistIn == 0) return 1; - cdist_ = cdistIn->Copy(); - return 0; -} diff --git a/src/DataSet_Cmatrix_NOMEM.h b/src/DataSet_Cmatrix_NOMEM.h deleted file mode 100644 index 13cf7f09b3..0000000000 --- a/src/DataSet_Cmatrix_NOMEM.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef INC_DATASET_CMATRIX_NOMEM_H -#define INC_DATASET_CMATRIX_NOMEM_H -#include "DataSet_Cmatrix.h" -/// Used when no pairwise distance matrix is to be stored; all calcs done on the fly. -class DataSet_Cmatrix_NOMEM : public DataSet_Cmatrix { - public: - DataSet_Cmatrix_NOMEM() : DataSet_Cmatrix(CMATRIX_NOMEM), cdist_(0) {} - ~DataSet_Cmatrix_NOMEM(); - static DataSet* Alloc() { return (DataSet*)new DataSet_Cmatrix_NOMEM(); } - // ----- DataSet functions ------------------- - size_t Size() const { return 0; } - void Info() const { return; } - void WriteBuffer(CpptrajFile&, SizeArray const&) const; - int Allocate(SizeArray const&) { return 0; } - /// \return Size in bytes of set - size_t MemUsageInBytes() const { return 0; } - // ----- Cmatrix functions ------------------- - /// \return an element indexed by sievedFrames. - inline double GetFdist(int f1, int f2) const { return cdist_->FrameDist(f1, f2); } - /// Set element at column/row to given value - void SetElement(int, int, double) {} - /// \return Actual number of elements in matrix //TODO put in Cmatrix - inline size_t Nelements() const; - /// \return size used by matrix in bytes - size_t DataSize() const { return sievedFrames_.DataSize(); } - /// \return Actual number of rows in the matrix // TODO put in Cmatrix - size_t Nrows() const { return sievedFrames_.ActualNframes(); } - /// \return Element at given index. - inline double GetElement(unsigned int) const; - /// \return true if matrix needs setup - bool NeedsSetup() const { return (cdist_ == 0); } - /// \return true if matrix needs calculation - bool NeedsCalc() const { return false; } - /// Indicate that no more distances will be added to matrix. - void Complete() {} - protected: - int AllocateCmatrix(size_t) { return 0; } - int SetCdist(ClusterDist*); - private: - ClusterDist* cdist_; -}; -// ----- Inline functions ------------------------------------------------------ - -size_t DataSet_Cmatrix_NOMEM::Nelements() const { - return (sievedFrames_.ActualNframes()*(sievedFrames_.ActualNframes()-1)) / 2; -} - -double DataSet_Cmatrix_NOMEM::GetElement(unsigned int idxIn) const { - int iidx = (int)idxIn; - return cdist_->FrameDist( sievedFrames_.IdxToFrame( iidx / sievedFrames_.ActualNframes() ), - sievedFrames_.IdxToFrame( iidx % sievedFrames_.ActualNframes() ) ); -} -#endif diff --git a/src/DataSet_PairwiseCache.cpp b/src/DataSet_PairwiseCache.cpp new file mode 100644 index 0000000000..fbae1ac7d7 --- /dev/null +++ b/src/DataSet_PairwiseCache.cpp @@ -0,0 +1,92 @@ +#include "DataSet_PairwiseCache.h" +#include "CpptrajStdio.h" + +using namespace Cpptraj; +using namespace Cluster; + +DataSet_PairwiseCache::DataSet_PairwiseCache() : + sieve_(0) +{} + +DataSet_PairwiseCache::DataSet_PairwiseCache(DataType t) : + DataSet(t, PWCACHE, TextFormat(TextFormat::DOUBLE, 12, 4), 2), + sieve_(0) +{} + +const char DataSet_PairwiseCache::PRESENT_ = 'F'; + +const char DataSet_PairwiseCache::ABSENT_ = 'T'; + +/** Set up frame number to matrix index for caching. This should be called + * by each inheriting DataSet_PairwiseCache's SetupCache routine. + */ +int DataSet_PairwiseCache::SetupFrameToIdx(Cframes const& framesToCache, unsigned int Ntotal) +{ + frameToIdx_.assign(Ntotal, -1); + int idx = 0; + for (Cframes_it it = framesToCache.begin(); it != framesToCache.end(); ++it) + frameToIdx_[*it] = idx++; +# ifdef DEBUG_CLUSTER + // DEBUG + mprintf("DEBUG: frameToMat\n"); + for (Cframes_it it = frameToIdx_.begin(); it != frameToIdx_.end(); ++it) + mprintf("\tframeToIdx_[%u] = %i\n", it - frameToIdx_.begin(), *it); +# endif + return 0; +} + +/** Check that the given frames match the already-cached frames. */ +bool DataSet_PairwiseCache::CachedFramesMatch(Cframes const& framesIn) const +{ + Cframes_it frm0 = framesIn.begin(); + for (int frm1 = 0; frm1 != (int)frameToIdx_.size(); frm1++) + { + if (frameToIdx_[frm1] != -1) { + if (frm0 == framesIn.end() || *frm0 != frm1) return false; + ++frm0; + } + } + return true; +} + +/** In given StatusArray, T means frame is present, F means not present. */ +int DataSet_PairwiseCache::SetupFromStatus(StatusArray const& frameIsPresent, int sieveIn) +{ + frameToIdx_.clear(); + frameToIdx_.reserve( frameIsPresent.size() ); + int idx = 0; + for (StatusArray::const_iterator it = frameIsPresent.begin(); + it != frameIsPresent.end(); ++it) + if (*it == PRESENT_) + frameToIdx_.push_back( idx++ ); + else + frameToIdx_.push_back( -1 ); + sieve_ = sieveIn; + return 0; +} + +/** \return Array containing frames present in the pairwise cache. */ +DataSet_PairwiseCache::Cframes DataSet_PairwiseCache::PresentFrames() const { + Cframes presentFrames; + presentFrames.reserve( Nrows() ); + int frm = 0; + for (frm = 0; frm != (int)frameToIdx_.size(); ++frm) + if (frameToIdx_[frm] != -1) + presentFrames.push_back( frm ); + return presentFrames; +} + +/** Print cached distances to stdout. */ +void DataSet_PairwiseCache::PrintCached() const { + for (Cframes::const_iterator it1 = FrameToIdx().begin(); it1 != FrameToIdx().end(); ++it1) + { + if (*it1 != -1) { + for (Cframes::const_iterator it2 = it1 + 1; it2 != FrameToIdx().end(); ++it2) + { + if (*it2 != -1) + mprintf("\t%li %li %f\n", it1-FrameToIdx().begin()+1, it2-FrameToIdx().begin()+1, + CachedDistance(*it1, *it2)); + } + } + } +} diff --git a/src/DataSet_PairwiseCache.h b/src/DataSet_PairwiseCache.h new file mode 100644 index 0000000000..71826b2a72 --- /dev/null +++ b/src/DataSet_PairwiseCache.h @@ -0,0 +1,78 @@ +#ifndef INC_DATASET_PAIRWISECACHE_H +#define INC_DATASET_PAIRWISECACHE_H +#include "DataSet.h" +#include "Cluster/Cframes.h" +/// Used to cache distances in a potentially sparse square symmetric matrix. +/** This is an abstract base class for storing pairwise distances + * for cluster analysis. The frameToIdx_ array maps the matrix indices to + * internal indices; indices for which there is no data are assigned -1. + */ +class DataSet_PairwiseCache : public DataSet { + public: + DataSet_PairwiseCache(); + /// This constructor should be used by child classes. + DataSet_PairwiseCache(DataType); + virtual ~DataSet_PairwiseCache() {} + + /// Class used to hold frame indices + typedef Cpptraj::Cluster::Cframes Cframes; + /// Class used to hold frame statuses (T = present) + typedef std::vector StatusArray; + + /// Character that means frame "present"; 'F' meaning frame was not sieve. + static const char PRESENT_; + /// Character that means frame "absent" - 'T' meaning frame was sieved. + static const char ABSENT_; + + //static DataSet* Alloc() { return (DataSet*)new DataSet_PairwiseCache(); } + // ----- DataSet functions ------------------- + //size_t Size() const { return 0; } + //void Info() const { return; } + //int Allocate(SizeArray const&) { return 1; } + //void Add(size_t, const void*) { return; } + //void WriteBuffer(CpptrajFile&, SizeArray const&) const { return; } + int Append(DataSet*) { return 1; } +# ifdef MPI + int Sync(size_t, std::vector const&, Parallel::Comm const&) { return 1; } +# endif + // ------------------------------------------- + /// \return distance between given cached frames (absolute frame numbers). + //virtual double GetFdist(int, int) const = 0; + /// \return distance between cached frames (internal indices). + virtual double CachedDistance(unsigned int, unsigned int) const = 0; + /// \return Number of rows (i.e. number of frames cached) in pairwise cache. TODO DataSet_2D + virtual size_t Nrows() const = 0; + /// Used to cache distances; expect internal indices, not absolute cluster frames. + virtual void SetElement(int, int, double) = 0; + /// Used to set up and allocate cache for total, frames to cache, sieve, and metric descrip. + virtual int SetupCache(unsigned int, Cframes const&, int, std::string const&) = 0; + // ------------------------------------------- + + /// \return The array for converting frame numbers to internal cache indices. + Cframes const& FrameToIdx() const { return frameToIdx_; } + /// \return True if given frames array matches cached frames. + bool CachedFramesMatch(Cframes const&) const; + /// \return Internal sieve value for bookkeeping + int SieveVal() const { return sieve_; } + /// \return Internal metric description for bookkeeping + std::string const& MetricDescrip() const { return metricDescription_; } + /// \return Array of frames present in the cache. + Cframes PresentFrames() const; + /// Print only cached distances. + void PrintCached() const; + + /// Used to set up frame indices from given status array. Record sieve value. + int SetupFromStatus(StatusArray const&, int); + protected: + /// Set up frame to internal index array using given frames and total frames. + int SetupFrameToIdx(Cframes const&, unsigned int); + /// Set internal sieve value for bookkeeping (should call from SetupCache). + void SetSieveVal(int s) { sieve_ = s; } + /// Set internal metric description for bookkeeping (should call from SetupCache). + void SetMetricDescrip(std::string const& m) { metricDescription_ = m; } + private: + Cframes frameToIdx_; ///< Hold indices for all cached frames, -1 for non-cached. + std::string metricDescription_; ///< Optional description of metric used to gen matrix. + int sieve_; ///< Optional sieve value used to select frames. +}; +#endif diff --git a/src/DataSet_PairwiseCache_MEM.cpp b/src/DataSet_PairwiseCache_MEM.cpp new file mode 100644 index 0000000000..7c6291d92e --- /dev/null +++ b/src/DataSet_PairwiseCache_MEM.cpp @@ -0,0 +1,42 @@ +#include "DataSet_PairwiseCache_MEM.h" +#include "CpptrajStdio.h" +#include "StringRoutines.h" + +int DataSet_PairwiseCache_MEM::Allocate(SizeArray const& sizeIn) { + int err = 0; + if (!sizeIn.empty()) { + // Sanity check. + if (sizeIn.size() > 1 && sizeIn[1] != sizeIn[0]) + mprintf("Warning: DataSet_PairwiseCache dimensions must be equal (%zu != %zu)\n" + "Warning: Matrix will be %zu x %zu upper triangle\n", + sizeIn[0], sizeIn[1], sizeIn[0], sizeIn[0]); + err = Mat_.resize(0, sizeIn[0]); // Upper triangle + } else + Mat_.clear(); + return err; +} + + +int DataSet_PairwiseCache_MEM::SetupCache(unsigned int Ntotal, Cframes const& framesToCache, + int sieve, std::string const& metricDescription) +{ + unsigned int sizeIn = framesToCache.size(); + if (sizeIn > 0) { + mprintf("\tEstimated pair-wise matrix memory usage: >= %s\n", + ByteString(Mat_.sizeInBytes( 0L, sizeIn ), BYTE_DECIMAL).c_str()); + try { Mat_.resize(0, sizeIn); } // Upper triangle + catch (const std::bad_alloc&) { + mprinterr("Error: Not enough memory to allocate pair-wise matrix.\n" + "Error: Consider using the 'sieve' keyword to reduce memory usage.\n"); + return 1; + } +# ifdef DEBUG_CLUSTER + mprintf("DEBUG: PairwiseMatrix_MEM set up for %i rows, size= %zu bytes.\n", + Mat_.Nrows(), Mat_.sizeInBytes()); +# endif + } else + Mat_.clear(); + SetSieveVal( sieve ); + SetMetricDescrip( metricDescription ); + return SetupFrameToIdx(framesToCache, Ntotal); +} diff --git a/src/DataSet_PairwiseCache_MEM.h b/src/DataSet_PairwiseCache_MEM.h new file mode 100644 index 0000000000..f53a060f97 --- /dev/null +++ b/src/DataSet_PairwiseCache_MEM.h @@ -0,0 +1,36 @@ +#ifndef INC_DATASET_PAIRWISECACHE_MEM_H +#define INC_DATASET_PAIRWISECACHE_MEM_H +#include "DataSet_PairwiseCache.h" +#include "Matrix.h" +/// +class DataSet_PairwiseCache_MEM : public DataSet_PairwiseCache { + public: + DataSet_PairwiseCache_MEM() : DataSet_PairwiseCache(PMATRIX_MEM) {} + static DataSet* Alloc() { return (DataSet*)new DataSet_PairwiseCache_MEM(); } + // ----- DataSet functions ------------------- + size_t Size() const { return Mat_.size(); } + void Info() const { return; } + int Allocate(SizeArray const&); + void Add(size_t, const void*) { return; } + void WriteBuffer(CpptrajFile&, SizeArray const&) const { return; } + size_t MemUsageInBytes() const { return Mat_.DataSize(); } +// int Append(DataSet*) { return 1; } +//# ifdef MPI +// int Sync(size_t, std::vector const&, Parallel::Comm const&) { return 1; } +//# endif + // ------------------------------------------- + //double GetFdist(int f1, int f2) const { return Mat_.element(FrameToMat()[f1], FrameToMat()[f2]); } + //double Frame_Distance(int, int) const; + // ----- PairwiseCache functions ------------- + double CachedDistance(unsigned int i1, unsigned int i2) const { return Mat_.element(i1, i2); } + //int CacheDistances(Cframes const&); + size_t Nrows() const { return Mat_.Nrows(); } + void SetElement(int col, int row, double val) { Mat_.setElement(col, row, val); } + int SetupCache(unsigned int, Cframes const&, int, std::string const&); + // ------------------------------------------- + float* Ptr() { return Mat_.Ptr(); } + float const* Ptr() const { return Mat_.Ptr(); } + private: + Matrix Mat_; ///< Hold cached distances +}; +#endif diff --git a/src/DataSet_PairwiseCache_NC.cpp b/src/DataSet_PairwiseCache_NC.cpp new file mode 100644 index 0000000000..4e171c2e69 --- /dev/null +++ b/src/DataSet_PairwiseCache_NC.cpp @@ -0,0 +1,32 @@ +#ifdef BINTRAJ +#include "DataSet_PairwiseCache_NC.h" +#include "CpptrajStdio.h" +#include "StringRoutines.h" // ByteString + +int DataSet_PairwiseCache_NC::SetupCache(unsigned int Ntotal, Cframes const& framesToCache, + int sieve, std::string const& metricDescription) +{ + if (Meta().Fname().empty()) { + mprinterr("Internal Error: NetCDF pairwise cache file name not set.\n"); + return 1; + } + unsigned int sizeIn = framesToCache.size(); + mprintf("\tPairwise cache file: '%s'\n", Meta().Fname().full()); + mprintf("\tEstimated pair-wise matrix disk usage: >= %s\n", + ByteString( file_.EstimatedDiskUsageInBytes(sizeIn), BYTE_DECIMAL ).c_str()); + if (file_.CreateCmatrix(Meta().Fname(), Ntotal, sizeIn, sieve, metricDescription)) + return 1; + // Write actual frames array if necessary + if (sieve != 1) { + if (file_.WriteFramesArray( framesToCache )) + return 1; + } + // Reopen in SHARE mode for random access + if (file_.ReopenSharedWrite( Meta().Fname() )) return 1; + // TODO - these are saved in the NetCDF file as well - remove redundancy? + SetSieveVal( sieve ); + SetMetricDescrip( metricDescription ); + + return SetupFrameToIdx(framesToCache, Ntotal); +} +#endif /* BINTRAJ */ diff --git a/src/DataSet_PairwiseCache_NC.h b/src/DataSet_PairwiseCache_NC.h new file mode 100644 index 0000000000..521e487ef1 --- /dev/null +++ b/src/DataSet_PairwiseCache_NC.h @@ -0,0 +1,34 @@ +#ifndef INC_DATASET_PAIRWISECACHE_NC_H +#define INC_DATASET_PAIRWISECACHE_NC_H +#ifdef BINTRAJ +#include "DataSet_PairwiseCache.h" +#include "Cluster/Cmatrix_NC.h" +/// Cache pairwise distances in NetCDF file. +class DataSet_PairwiseCache_NC : public DataSet_PairwiseCache { + public: + DataSet_PairwiseCache_NC() : DataSet_PairwiseCache(PMATRIX_NC) {} + static DataSet* Alloc() { return (DataSet*)new DataSet_PairwiseCache_NC(); } + // ----- DataSet functions ------------------- + size_t Size() const { return file_.MatrixSize(); } + void Info() const { return; } + int Allocate(SizeArray const&) { return 0; } + void Add(size_t, const void*) { return; } + void WriteBuffer(CpptrajFile&, SizeArray const&) const { return; } + size_t MemUsageInBytes() const { return 0; } +// int Append(DataSet*) { return 1; } +//# ifdef MPI +// int Sync(size_t, std::vector const&, Parallel::Comm const&) { return 1; } +//# endif + // ----- PairwiseCache functions ------------- + double CachedDistance(unsigned int i1, unsigned int i2) const { + return file_.GetCmatrixElement(i1, i2); + } + size_t Nrows() const { return file_.MatrixRows(); } + void SetElement(int x, int y, double val) { file_.WriteCmatrixElement(x, y, val); } + int SetupCache(unsigned int, Cframes const&, int, std::string const&); + // ------------------------------------------- + private: + Cpptraj::Cluster::Cmatrix_NC file_; ///< Hold cached distances on disk +}; +#endif /* BINTRAJ */ +#endif diff --git a/src/FindDepend.cpp b/src/FindDepend.cpp index fdd052cdbd..0f1430d48b 100644 --- a/src/FindDepend.cpp +++ b/src/FindDepend.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace std; @@ -50,12 +51,40 @@ bool IgnoreHeader(const char* headername) { return false; } -/** Add list of dependencies for the given file to appropriate map. */ -void GetDependencies(string const& filename) { - char buffer[BUFFERSIZE+1]; - char headername[BUFFERSIZE+1]; +/** Try to simplify a directory prefix that may contain '../'. */ +std::string SimplifyDirPrefix(std::string const& dirPrefix) { + if (dirPrefix.empty()) return dirPrefix; + + std::vector slashes; + for (std::string::const_iterator it = dirPrefix.begin(); it != dirPrefix.end(); ++it) + if ( *it == '/' ) { + slashes.push_back( it - dirPrefix.begin() ); + //printf("\tSlash at %li\n", slashes.back()); + } + // If only one slash, nothing to simplify + if (slashes.size() < 2) return dirPrefix; + // 012 + // Check for ../ + // 210 + for (std::vector::const_iterator it = slashes.begin(); it != slashes.end(); ++it) + { + if (*it > 1) { + if ( dirPrefix[*it-2] == '.' && dirPrefix[*it-1] == '.' ) { + //printf("\t../ at %li\n", *it); + // If this is ../ corresponding to 2nd slash, negates everything from the beginning to here + if (it - slashes.begin() == 1) { + std::string newStr = dirPrefix.substr(*it+1, dirPrefix.size() - *it+1); + //printf("\tNew prefix= %s\n", newStr.c_str()); + return newStr; + } + } + } + } + return dirPrefix; +} + +void SplitIntoDirAndBase(std::string& filename, std::string& dirPrefix, std::string& baseName) { // Determine path - string baseName, dirPrefix; size_t found = filename.find_last_of("/"); if (found == std::string::npos) { baseName = filename; @@ -65,10 +94,27 @@ void GetDependencies(string const& filename) { dirPrefix = filename.substr(0, found+1); } //printf("DEBUG: Dir='%s' Base='%s'\n", dirPrefix.c_str(), baseName.c_str()); + // Ascertain whether we can simplify the directory prefix + std::string newDirPrefix = SimplifyDirPrefix( dirPrefix ); + if (!dirPrefix.empty() && newDirPrefix.empty()) { + dirPrefix.clear(); + filename = baseName; + } +} + +/** Add list of dependencies for the given file to appropriate map. */ +void GetDependencies(string const& filenameIn) { + std::string filename = filenameIn; + char buffer[BUFFERSIZE+1]; + char headername[BUFFERSIZE+1]; + // Determine path + string baseName, dirPrefix; + SplitIntoDirAndBase(filename, dirPrefix, baseName); + // Determine type FileType type; string ext; - found = filename.find_last_of("."); + size_t found = filename.find_last_of("."); if (found != string::npos) ext = filename.substr(found); @@ -119,8 +165,12 @@ void GetDependencies(string const& filename) { // Get rid of last " size_t pos = strlen(headername); if (headername[pos-1]=='"') headername[pos-1]='\0'; - if (!IgnoreHeader(headername)) - depends.insert( dirPrefix + string(headername) ); + if (!IgnoreHeader(headername)) { + std::string newFileName = dirPrefix + string(headername); + std::string newdir, newbase; + SplitIntoDirAndBase(newFileName, newdir, newbase); + depends.insert( newFileName ); + } } //else //printf("\tSkipping system header line: %s", buffer); } diff --git a/src/Makefile b/src/Makefile index 2ef782e335..a5b3470d2c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,6 +7,8 @@ DEL_FILE = /bin/rm -f OBJECTS=$(SOURCES:.cpp=.o) $(CSOURCES:.c=.o) +CLUSTER_TARGET=Cluster/libcpptraj_cluster.a + # Default target: cpptraj only all: cpptraj$(SFX)$(EXE) @@ -17,8 +19,8 @@ install: $(INSTALL_TARGETS) install_cpptraj: cpptraj$(SFX)$(EXE) mv cpptraj$(SFX)$(EXE) $(CPPTRAJBIN) -cpptraj$(SFX)$(EXE): $(OBJECTS) $(FFT_TARGET) $(READLINE_TARGET) $(CUDA_TARGET) $(XDRFILE_TARGET) $(ARPACK_TARGET) $(TNGFILE_TARGET) - $(CXX) -o cpptraj$(SFX)$(EXE) $(OBJECTS) $(CUDA_TARGET) $(FFT_TARGET) $(READLINE_LIB) $(CPPTRAJ_LIB) $(LDFLAGS) +cpptraj$(SFX)$(EXE): $(OBJECTS) $(FFT_TARGET) $(READLINE_TARGET) $(CUDA_TARGET) $(CLUSTER_TARGET) $(XDRFILE_TARGET) $(ARPACK_TARGET) $(TNGFILE_TARGET) + $(CXX) -o cpptraj$(SFX)$(EXE) $(OBJECTS) $(CUDA_TARGET) $(CLUSTER_TARGET) $(FFT_TARGET) $(READLINE_LIB) $(CPPTRAJ_LIB) $(LDFLAGS) # libcpptraj --------------------------- # Rule to make libcpptraj-specific objects @@ -27,8 +29,8 @@ cpptraj$(SFX)$(EXE): $(OBJECTS) $(FFT_TARGET) $(READLINE_TARGET) $(CUDA_TARGET) libcpptraj: $(LIBCPPTRAJ_TARGET) -$(CPPTRAJLIB)/libcpptraj$(SHARED_SUFFIX): $(LIBCPPTRAJ_OBJECTS) $(FFT_TARGET) $(CUDA_TARGET) $(XDRFILE_TARGET) $(ARPACK_TARGET) $(TNGFILE_TARGET) - $(CXX) -shared -o $(CPPTRAJLIB)/libcpptraj$(SHARED_SUFFIX) $(LIBCPPTRAJ_OBJECTS) $(FFT_TARGET) $(CUDA_TARGET) $(CPPTRAJ_LIB) $(LDFLAGS) +$(CPPTRAJLIB)/libcpptraj$(SHARED_SUFFIX): $(LIBCPPTRAJ_OBJECTS) $(FFT_TARGET) $(CUDA_TARGET) $(CLUSTER_TARGET) $(XDRFILE_TARGET) $(ARPACK_TARGET) $(TNGFILE_TARGET) + $(CXX) -shared -o $(CPPTRAJLIB)/libcpptraj$(SHARED_SUFFIX) $(LIBCPPTRAJ_OBJECTS) $(FFT_TARGET) $(CUDA_TARGET) $(CLUSTER_TARGET) $(CPPTRAJ_LIB) $(LDFLAGS) # Data directory ----------------------- install_dat: @@ -101,8 +103,11 @@ noarpack: cuda_kernels/libcpptraj_cuda.a: ../external.config.h cd cuda_kernels && $(MAKE) all +$(CLUSTER_TARGET):: + cd Cluster && $(MAKE) all + # Dependency targets -findDepend: FindDepend.o +findDepend: FindDepend.cpp FindDepend.o $(CXX) -o findDepend FindDepend.o depend: findDepend @@ -118,6 +123,7 @@ clean: cd xdrfile && $(MAKE) clean cd arpack && $(MAKE) clean cd cuda_kernels && $(MAKE) clean + cd Cluster && $(MAKE) clean cd tng && $(MAKE) clean uninstall_lib: @@ -136,9 +142,10 @@ uninstall_inc: uninstall: uninstall_lib uninstall_inc $(DEL_FILE) $(CPPTRAJBIN)/cpptraj$(SFX)$(EXE) $(DEL_FILE) $(CPPTRAJLIB)/libcpptraj$(SHARED_SUFFIX) - cd readline && make uninstall - cd xdrfile && make uninstall - cd cuda_kernels && make uninstall + cd readline && $(MAKE) uninstall + cd xdrfile && $(MAKE) uninstall + cd cuda_kernels && $(MAKE) uninstall + cd Cluster && $(MAKE) uninstall # Header dependencies include cpptrajdepend diff --git a/src/Matrix.h b/src/Matrix.h index cc83b63df1..816ec1e916 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -26,7 +26,7 @@ template class Matrix { size_t size() const { return nelements_; } /// \return current matrix type. MType Type() const { return type_; } - /// \return estimated size in bytes. + /// \return estimated size in bytes for given number of columns and rows. static size_t sizeInBytes(size_t,size_t); /// Set up matrix for given number of cols and rows. int resize(size_t,size_t); @@ -58,9 +58,12 @@ template class Matrix { iterator end() const { return elements_ + nelements_; } /// \return memory used by matrix in bytes. size_t DataSize() const { - return (nelements_*sizeof(T)) + sizeof(T) + - (5 * sizeof(size_t) + sizeof(MType) + - sizeof(long int(*)())); + return (nelements_*sizeof(T)) + // elements_ array + sizeof(T*) + // elements_ + sizeof(T) + // diagElt_ + (5 * sizeof(size_t)) + // ncols_, nrows_, nelements_, maxElements_, currentElement_ + sizeof(MType) + // type_ + sizeof(long int(*)()); // indexFxn_ } /// Clear matrix void clear() { diff --git a/src/SymmetricRmsdCalc.cpp b/src/SymmetricRmsdCalc.cpp index f145a50c8a..91c06de381 100644 --- a/src/SymmetricRmsdCalc.cpp +++ b/src/SymmetricRmsdCalc.cpp @@ -35,8 +35,13 @@ int SymmetricRmsdCalc::SetupSymmRMSD(Topology const& topIn, AtomMask const& tgtM Iarray SelectedIdx( topIn.Natom(), -1 ); int tgtIdx = 0; for (int originalAtom = 0; originalAtom != topIn.Natom(); ++originalAtom) - if ( originalAtom == tgtMask[tgtIdx] ) + { + if ( originalAtom == tgtMask[tgtIdx] ) { SelectedIdx[originalAtom] = tgtIdx++; + if (tgtIdx == tgtMask.Nselected()) + break; + } + } if (debug_ > 0) { mprintf("DEBUG: Original atom -> Selected Index mapping:\n"); for (int originalAtom = 0; originalAtom != topIn.Natom(); ++originalAtom) diff --git a/src/Version.h b/src/Version.h index 6a9e15fce1..1c3a03c74d 100644 --- a/src/Version.h +++ b/src/Version.h @@ -12,7 +12,7 @@ * Whenever a number that precedes is incremented, all subsequent * numbers should be reset to 0. */ -#define CPPTRAJ_INTERNAL_VERSION "V5.4.2" +#define CPPTRAJ_INTERNAL_VERSION "V6.0.0" /// PYTRAJ relies on this #define CPPTRAJ_VERSION_STRING CPPTRAJ_INTERNAL_VERSION #endif diff --git a/src/cpptrajdepend b/src/cpptrajdepend index aeefaa2d9f..f32546bd69 100644 --- a/src/cpptrajdepend +++ b/src/cpptrajdepend @@ -15,7 +15,7 @@ Action_Center.o : Action_Center.cpp Action.h ActionState.h Action_Center.h ArgLi Action_Channel.o : Action_Channel.cpp Action.h ActionState.h Action_Channel.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridFlt.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h Grid.h GridBin.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_CheckChirality.o : Action_CheckChirality.cpp Action.h ActionState.h Action_CheckChirality.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mesh.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h SymbolExporting.h TextFormat.h Timer.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h Action_CheckStructure.o : Action_CheckStructure.cpp Action.h ActionState.h Action_CheckStructure.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_double.h DataSet_integer.h DataSet_string.h Dimension.h DispatchObject.h ExclusionArray.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StructureCheck.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Action_Closest.o : Action_Closest.cpp Action.h ActionState.h ActionTopWriter.h Action_Closest.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h ImageRoutines.h ImageTypes.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/../ImageOption.h cuda_kernels/kernel_wrappers.cuh +Action_Closest.o : Action_Closest.cpp Action.h ActionState.h ActionTopWriter.h Action_Closest.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h ImageRoutines.h ImageTypes.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/kernel_wrappers.cuh Action_ClusterDihedral.o : Action_ClusterDihedral.cpp Action.h ActionState.h Action_ClusterDihedral.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_integer.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TorsionRoutines.h TypeNameHolder.h Unit.h Vec3.h Action_Contacts.o : Action_Contacts.cpp Action.h ActionState.h Action_Contacts.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_CreateCrd.o : Action_CreateCrd.cpp Action.h ActionState.h Action_CreateCrd.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CompactFrameArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -86,13 +86,13 @@ Action_Vector.o : Action_Vector.cpp Action.h ActionState.h Action_Vector.h ArgLi Action_VelocityAutoCorr.o : Action_VelocityAutoCorr.cpp Action.h ActionState.h Action_VelocityAutoCorr.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h ComplexArray.h Constants.h CoordinateInfo.h Corr.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Vector.h DataSet_double.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h PubFFT.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Volmap.o : Action_Volmap.cpp Action.h ActionState.h Action_Volmap.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridDbl.h DataSet_GridFlt.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h Grid.h GridBin.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SplineFxnTable.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Action_Volume.o : Action_Volume.cpp Action.h ActionState.h Action_Volume.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Action_Watershell.o : Action_Watershell.cpp Action.h ActionState.h Action_Watershell.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h ImageRoutines.h ImageTypes.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/../ImageOption.h cuda_kernels/kernel_wrappers.cuh +Action_Watershell.o : Action_Watershell.cpp Action.h ActionState.h Action_Watershell.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h DistRoutines.h FileIO.h FileName.h FileTypes.h Frame.h ImageOption.h ImageRoutines.h ImageTypes.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/kernel_wrappers.cuh Action_XtalSymm.o : Action_XtalSymm.cpp Action.h ActionState.h Action_XtalSymm.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SpaceGroup.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h AnalysisList.o : AnalysisList.cpp ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Analysis_AmdBias.o : Analysis_AmdBias.cpp ActionState.h Analysis.h AnalysisState.h Analysis_AmdBias.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_double.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Analysis_AutoCorr.o : Analysis_AutoCorr.cpp ActionState.h Analysis.h AnalysisState.h Analysis_AutoCorr.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h ComplexArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Vector.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Analysis_Average.o : Analysis_Average.cpp ActionState.h Analysis.h AnalysisState.h Analysis_Average.h ArgList.h Array1D.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Analysis_Clustering.o : Analysis_Clustering.cpp ActionFrameCounter.h ActionState.h Analysis.h AnalysisState.h Analysis_Clustering.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h BaseIOtype.h Box.h ClusterDist.h ClusterList.h ClusterMatrix.h ClusterNode.h ClusterSieve.h Cluster_DBSCAN.h Cluster_DPeaks.h Cluster_HierAgglo.h Cluster_Kmeans.h Cluster_ReadInfo.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_float.h DataSet_integer.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Random.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TrajectoryFile.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h +Analysis_Clustering.o : Analysis_Clustering.cpp ActionState.h Analysis.h AnalysisState.h Analysis_Clustering.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Cluster/Algorithm.h Cluster/BestReps.h Cluster/CentroidArray.h Cluster/Cframes.h Cluster/Control.h Cluster/DrawGraph.h Cluster/List.h Cluster/Metric.h Cluster/MetricArray.h Cluster/Node.h Cluster/Sieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Analysis_ConstantPHStats.o : Analysis_ConstantPHStats.cpp ActionState.h Analysis.h AnalysisState.h Analysis_ConstantPHStats.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h Cph.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mesh.h DataSet_pH.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Analysis_Corr.o : Analysis_Corr.cpp ActionState.h Analysis.h AnalysisState.h Analysis_Corr.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h ComplexArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Vector.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h Analysis_CrankShaft.o : Analysis_CrankShaft.cpp ActionState.h Analysis.h AnalysisState.h Analysis_CrankShaft.h Analysis_Statistics.h ArgList.h Array1D.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_float.h DataSet_integer.h DataSet_string.h Dimension.h DispatchObject.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -146,21 +146,11 @@ ByteRoutines.o : ByteRoutines.cpp CIFfile.o : CIFfile.cpp Atom.h BufferedLine.h CIFfile.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h NameType.h Parallel.h SymbolExporting.h CharMask.o : CharMask.cpp Atom.h CharMask.h CpptrajStdio.h MaskToken.h Molecule.h NameType.h Residue.h Segment.h SymbolExporting.h Unit.h CharmmParamFile.o : CharmmParamFile.cpp ArgList.h AtomType.h BufferedLine.h CharmmParamFile.h Constants.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h StringRoutines.h TypeNameHolder.h -ClusterDist.o : ClusterDist.cpp ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h Constants.h CoordinateInfo.h CpptrajFile.h DataSet.h DataSet_1D.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -ClusterList.o : ClusterList.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterList.h ClusterNode.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PDBfile.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h ClusterMap.o : ClusterMap.cpp AssociatedData.h ClusterMap.h Constants.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_2D.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h ProgressBar.h ProgressTimer.h Range.h TextFormat.h Timer.h -ClusterMatrix.o : ClusterMatrix.cpp ArrayIterator.h ClusterMatrix.h CpptrajStdio.h Matrix.h -ClusterNode.o : ClusterNode.cpp ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterNode.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -ClusterSieve.o : ClusterSieve.cpp ClusterSieve.h Random.h -Cluster_DBSCAN.o : Cluster_DBSCAN.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h BaseIOtype.h Box.h ClusterDist.h ClusterList.h ClusterNode.h ClusterSieve.h Cluster_DBSCAN.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_Cmatrix.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_MatrixDbl.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Cluster_DPeaks.o : Cluster_DPeaks.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterList.h ClusterNode.h ClusterSieve.h Cluster_DPeaks.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h DataSet_Mesh.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReplicaDimArray.h Residue.h Segment.h Spline.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Cluster_HierAgglo.o : Cluster_HierAgglo.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterList.h ClusterMatrix.h ClusterNode.h ClusterSieve.h Cluster_HierAgglo.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Cluster_Kmeans.o : Cluster_Kmeans.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterList.h ClusterNode.h ClusterSieve.h Cluster_Kmeans.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Random.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -Cluster_ReadInfo.o : Cluster_ReadInfo.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h BufferedLine.h ClusterDist.h ClusterList.h ClusterNode.h ClusterSieve.h Cluster_ReadInfo.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h Cmd.o : Cmd.cpp Cmd.h DispatchObject.h CmdInput.o : CmdInput.cpp CmdInput.h StringRoutines.h CmdList.o : CmdList.cpp Cmd.h CmdList.h DispatchObject.h -Command.o : Command.cpp Action.h ActionFrameCounter.h ActionList.h ActionState.h ActionTopWriter.h Action_Align.h Action_Angle.h Action_AreaPerMol.h Action_AtomMap.h Action_AtomicCorr.h Action_AtomicFluct.h Action_AutoImage.h Action_Average.h Action_Bounds.h Action_Box.h Action_Center.h Action_Channel.h Action_CheckChirality.h Action_CheckStructure.h Action_Closest.h Action_ClusterDihedral.h Action_Contacts.h Action_CreateCrd.h Action_CreateReservoir.h Action_DNAionTracker.h Action_DSSP.h Action_Density.h Action_Diffusion.h Action_Dihedral.h Action_DihedralRMS.h Action_Dipole.h Action_DistRmsd.h Action_Distance.h Action_Energy.h Action_Esander.h Action_FilterByData.h Action_FixAtomOrder.h Action_FixImagedBonds.h Action_GIST.h Action_Grid.h Action_GridFreeEnergy.h Action_HydrogenBond.h Action_Image.h Action_InfraredSpectrum.h Action_Jcoupling.h Action_LESsplit.h Action_LIE.h Action_LipidOrder.h Action_MakeStructure.h Action_Mask.h Action_Matrix.h Action_MinImage.h Action_Molsurf.h Action_MultiDihedral.h Action_MultiPucker.h Action_MultiVector.h Action_NAstruct.h Action_NMRrst.h Action_NativeContacts.h Action_OrderParameter.h Action_Outtraj.h Action_PairDist.h Action_Pairwise.h Action_Principal.h Action_Projection.h Action_Pucker.h Action_Radgyr.h Action_Radial.h Action_RandomizeIons.h Action_Remap.h Action_ReplicateCell.h Action_Rmsd.h Action_Rotate.h Action_RunningAvg.h Action_STFC_Diffusion.h Action_Scale.h Action_SetVelocity.h Action_Spam.h Action_Strip.h Action_Surf.h Action_SymmetricRmsd.h Action_Temperature.h Action_Time.h Action_Translate.h Action_Unstrip.h Action_Unwrap.h Action_Vector.h Action_VelocityAutoCorr.h Action_Volmap.h Action_Volume.h Action_Watershell.h Action_XtalSymm.h Analysis.h AnalysisList.h AnalysisState.h Analysis_AmdBias.h Analysis_AutoCorr.h Analysis_Average.h Analysis_Clustering.h Analysis_ConstantPHStats.h Analysis_Corr.h Analysis_CrankShaft.h Analysis_CrdFluct.h Analysis_CrossCorr.h Analysis_CurveFit.h Analysis_Divergence.h Analysis_EvalPlateau.h Analysis_FFT.h Analysis_HausdorffDistance.h Analysis_Hist.h Analysis_IRED.h Analysis_Integrate.h Analysis_KDE.h Analysis_Lifetime.h Analysis_LowestCurve.h Analysis_Matrix.h Analysis_MeltCurve.h Analysis_Modes.h Analysis_MultiHist.h Analysis_Multicurve.h Analysis_Overlap.h Analysis_PhiPsi.h Analysis_Regression.h Analysis_RemLog.h Analysis_Rms2d.h Analysis_RmsAvgCorr.h Analysis_Rotdif.h Analysis_RunningAvg.h Analysis_Slope.h Analysis_Spline.h Analysis_State.h Analysis_Statistics.h Analysis_TI.h Analysis_Timecorr.h Analysis_VectorMath.h Analysis_Wavelet.h ArgList.h Array1D.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h AxisType.h BaseIOtype.h Box.h BoxArgs.h BufferedLine.h CharMask.h ClusterDist.h ClusterList.h ClusterMap.h ClusterNode.h ClusterSieve.h Cmd.h CmdInput.h CmdList.h Command.h CompactFrameArray.h ComplexArray.h Constants.h Constraints.h ControlBlock.h ControlBlock_For.h CoordinateInfo.h Corr.h Cph.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataFilter.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Cmatrix.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_GridFlt.h DataSet_Mat3x3.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Mesh.h DataSet_Modes.h DataSet_RemLog.h DataSet_Vector.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_integer_mem.h DataSet_pH.h DataSet_string.h Deprecated.h DihedralSearch.h Dimension.h DispatchObject.h Energy.h Energy_Sander.h EnsembleIn.h EnsembleOutList.h Ewald.h EwaldOptions.h Ewald_ParticleMesh.h ExclusionArray.h Exec.h Exec_AddMissingRes.h Exec_Analyze.h Exec_Calc.h Exec_CatCrd.h Exec_Change.h Exec_ClusterMap.h Exec_CombineCoords.h Exec_Commands.h Exec_CompareTop.h Exec_CrdAction.h Exec_CrdOut.h Exec_CreateSet.h Exec_DataFile.h Exec_DataFilter.h Exec_DataSetCmd.h Exec_Emin.h Exec_Flatten.h Exec_GenerateAmberRst.h Exec_Graft.h Exec_Help.h Exec_LoadCrd.h Exec_LoadTraj.h Exec_ParallelAnalysis.h Exec_ParmBox.h Exec_ParmSolvent.h Exec_ParmStrip.h Exec_ParmWrite.h Exec_PermuteDihedrals.h Exec_Precision.h Exec_PrepareForLeap.h Exec_PrintData.h Exec_Random.h Exec_ReadData.h Exec_ReadEnsembleData.h Exec_ReadInput.h Exec_RotateDihedral.h Exec_RunAnalysis.h Exec_ScaleDihedralK.h Exec_SequenceAlign.h Exec_Set.h Exec_Show.h Exec_SortEnsembleData.h Exec_SplitCoords.h Exec_System.h Exec_Top.h Exec_Traj.h Exec_UpdateParameters.h Exec_ViewRst.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h GIST_PME.h Grid.h GridAction.h GridBin.h HistBin.h Hungarian.h ImageOption.h ImageTypes.h InputTrajCommon.h MapAtom.h MaskArray.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h NetcdfFile.h OnlineVarT.h OutputTrajCommon.h PDBfile.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PubFFT.h Pucker.h Pucker_PuckerMask.h Pucker_PuckerSearch.h Pucker_PuckerToken.h RPNcalc.h Random.h Range.h ReferenceAction.h ReferenceFrame.h RemdReservoirNC.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h Spline.h SplineFxnTable.h StructureCheck.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajectoryFile.h Trajin.h TrajinList.h TrajoutList.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/GistCudaSetup.cuh helpme_standalone.h molsurf.h +Command.o : Command.cpp Action.h ActionFrameCounter.h ActionList.h ActionState.h ActionTopWriter.h Action_Align.h Action_Angle.h Action_AreaPerMol.h Action_AtomMap.h Action_AtomicCorr.h Action_AtomicFluct.h Action_AutoImage.h Action_Average.h Action_Bounds.h Action_Box.h Action_Center.h Action_Channel.h Action_CheckChirality.h Action_CheckStructure.h Action_Closest.h Action_ClusterDihedral.h Action_Contacts.h Action_CreateCrd.h Action_CreateReservoir.h Action_DNAionTracker.h Action_DSSP.h Action_Density.h Action_Diffusion.h Action_Dihedral.h Action_DihedralRMS.h Action_Dipole.h Action_DistRmsd.h Action_Distance.h Action_Energy.h Action_Esander.h Action_FilterByData.h Action_FixAtomOrder.h Action_FixImagedBonds.h Action_GIST.h Action_Grid.h Action_GridFreeEnergy.h Action_HydrogenBond.h Action_Image.h Action_InfraredSpectrum.h Action_Jcoupling.h Action_LESsplit.h Action_LIE.h Action_LipidOrder.h Action_MakeStructure.h Action_Mask.h Action_Matrix.h Action_MinImage.h Action_Molsurf.h Action_MultiDihedral.h Action_MultiPucker.h Action_MultiVector.h Action_NAstruct.h Action_NMRrst.h Action_NativeContacts.h Action_OrderParameter.h Action_Outtraj.h Action_PairDist.h Action_Pairwise.h Action_Principal.h Action_Projection.h Action_Pucker.h Action_Radgyr.h Action_Radial.h Action_RandomizeIons.h Action_Remap.h Action_ReplicateCell.h Action_Rmsd.h Action_Rotate.h Action_RunningAvg.h Action_STFC_Diffusion.h Action_Scale.h Action_SetVelocity.h Action_Spam.h Action_Strip.h Action_Surf.h Action_SymmetricRmsd.h Action_Temperature.h Action_Time.h Action_Translate.h Action_Unstrip.h Action_Unwrap.h Action_Vector.h Action_VelocityAutoCorr.h Action_Volmap.h Action_Volume.h Action_Watershell.h Action_XtalSymm.h Analysis.h AnalysisList.h AnalysisState.h Analysis_AmdBias.h Analysis_AutoCorr.h Analysis_Average.h Analysis_Clustering.h Analysis_ConstantPHStats.h Analysis_Corr.h Analysis_CrankShaft.h Analysis_CrdFluct.h Analysis_CrossCorr.h Analysis_CurveFit.h Analysis_Divergence.h Analysis_EvalPlateau.h Analysis_FFT.h Analysis_HausdorffDistance.h Analysis_Hist.h Analysis_IRED.h Analysis_Integrate.h Analysis_KDE.h Analysis_Lifetime.h Analysis_LowestCurve.h Analysis_Matrix.h Analysis_MeltCurve.h Analysis_Modes.h Analysis_MultiHist.h Analysis_Multicurve.h Analysis_Overlap.h Analysis_PhiPsi.h Analysis_Regression.h Analysis_RemLog.h Analysis_Rms2d.h Analysis_RmsAvgCorr.h Analysis_Rotdif.h Analysis_RunningAvg.h Analysis_Slope.h Analysis_Spline.h Analysis_State.h Analysis_Statistics.h Analysis_TI.h Analysis_Timecorr.h Analysis_VectorMath.h Analysis_Wavelet.h ArgList.h Array1D.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h AxisType.h BaseIOtype.h Box.h BoxArgs.h BufferedLine.h CharMask.h Cluster/Algorithm.h Cluster/BestReps.h Cluster/CentroidArray.h Cluster/Cframes.h Cluster/Control.h Cluster/DrawGraph.h Cluster/List.h Cluster/Metric.h Cluster/MetricArray.h Cluster/Node.h Cluster/Sieve.h ClusterMap.h Cmd.h CmdInput.h CmdList.h Command.h CompactFrameArray.h ComplexArray.h Constants.h Constraints.h ControlBlock.h ControlBlock_For.h CoordinateInfo.h Corr.h Cph.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataFilter.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_GridFlt.h DataSet_Mat3x3.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Mesh.h DataSet_Modes.h DataSet_RemLog.h DataSet_Vector.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_integer_mem.h DataSet_pH.h DataSet_string.h Deprecated.h DihedralSearch.h Dimension.h DispatchObject.h Energy.h Energy_Sander.h EnsembleIn.h EnsembleOutList.h Ewald.h EwaldOptions.h Ewald_ParticleMesh.h ExclusionArray.h Exec.h Exec_AddMissingRes.h Exec_Analyze.h Exec_Calc.h Exec_CatCrd.h Exec_Change.h Exec_ClusterMap.h Exec_CombineCoords.h Exec_Commands.h Exec_CompareTop.h Exec_CrdAction.h Exec_CrdOut.h Exec_CreateSet.h Exec_DataFile.h Exec_DataFilter.h Exec_DataSetCmd.h Exec_Emin.h Exec_Flatten.h Exec_GenerateAmberRst.h Exec_Graft.h Exec_Help.h Exec_LoadCrd.h Exec_LoadTraj.h Exec_ParallelAnalysis.h Exec_ParmBox.h Exec_ParmSolvent.h Exec_ParmStrip.h Exec_ParmWrite.h Exec_PermuteDihedrals.h Exec_Precision.h Exec_PrepareForLeap.h Exec_PrintData.h Exec_Random.h Exec_ReadData.h Exec_ReadEnsembleData.h Exec_ReadInput.h Exec_RotateDihedral.h Exec_RunAnalysis.h Exec_ScaleDihedralK.h Exec_SequenceAlign.h Exec_Set.h Exec_Show.h Exec_SortEnsembleData.h Exec_SplitCoords.h Exec_System.h Exec_Top.h Exec_Traj.h Exec_UpdateParameters.h Exec_ViewRst.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h GIST_PME.h Grid.h GridAction.h GridBin.h HistBin.h Hungarian.h ImageOption.h ImageTypes.h InputTrajCommon.h MapAtom.h MaskArray.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h NetcdfFile.h OnlineVarT.h OutputTrajCommon.h PDBfile.h PairList.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PubFFT.h Pucker.h Pucker_PuckerMask.h Pucker_PuckerSearch.h Pucker_PuckerToken.h RPNcalc.h Random.h Range.h ReferenceAction.h ReferenceFrame.h RemdReservoirNC.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h Spline.h SplineFxnTable.h StructureCheck.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajectoryFile.h Trajin.h TrajinList.h TrajoutList.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h cuda_kernels/GistCudaSetup.cuh helpme_standalone.h molsurf.h CompactFrameArray.o : CompactFrameArray.cpp Box.h CompactFrameArray.h CoordinateInfo.h CpptrajStdio.h Matrix_3x3.h Parallel.h ReplicaDimArray.h Vec3.h ComplexArray.o : ComplexArray.cpp ArrayIterator.h ComplexArray.h Constraints.o : Constraints.cpp ArgList.h Atom.h AtomMask.h AtomType.h Box.h CharMask.h Constants.h Constraints.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -173,7 +163,7 @@ CpptrajFile.o : CpptrajFile.cpp CpptrajFile.h CpptrajStdio.h FileIO.h FileIO_Bzi CpptrajState.o : CpptrajState.cpp Action.h ActionList.h ActionState.h Action_CreateCrd.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CompactFrameArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajState.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_Coords_TRJ.h DataSet_Topology.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleNavigator.h EnsembleOutList.h FileIO.h FileName.h FileTypes.h Frame.h FrameArray.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Random.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajFrameIndex.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h CpptrajStdio.o : CpptrajStdio.cpp Parallel.h CurveFit.o : CurveFit.cpp CurveFit.h -DataFile.o : DataFile.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h Cph.h CpptrajFile.h CpptrajStdio.h DataFile.h DataIO.h DataIO_CCP4.h DataIO_CharmmFastRep.h DataIO_CharmmOutput.h DataIO_CharmmRepLog.h DataIO_CharmmRtfPrm.h DataIO_Cmatrix.h DataIO_Cpout.h DataIO_Evecs.h DataIO_Gnuplot.h DataIO_Grace.h DataIO_Mdout.h DataIO_NC_Cmatrix.h DataIO_OpenDx.h DataIO_Peaks.h DataIO_RemLog.h DataIO_Std.h DataIO_VecTraj.h DataIO_XVG.h DataIO_Xplor.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Cmatrix_MEM.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_RemLog.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NC_Cmatrix.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TrajectoryFile.h TypeNameHolder.h Unit.h Vec3.h +DataFile.o : DataFile.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Cluster/Cframes.h Cluster/Cmatrix_NC.h Constants.h CoordinateInfo.h Cph.h CpptrajFile.h CpptrajStdio.h DataFile.h DataIO.h DataIO_CCP4.h DataIO_CharmmFastRep.h DataIO_CharmmOutput.h DataIO_CharmmRepLog.h DataIO_CharmmRtfPrm.h DataIO_Cmatrix_Binary.h DataIO_Cmatrix_NC.h DataIO_Cpout.h DataIO_Evecs.h DataIO_Gnuplot.h DataIO_Grace.h DataIO_Mdout.h DataIO_OpenDx.h DataIO_Peaks.h DataIO_RemLog.h DataIO_Std.h DataIO_VecTraj.h DataIO_XVG.h DataIO_Xplor.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_PairwiseCache.h DataSet_PairwiseCache_MEM.h DataSet_RemLog.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajectoryFile.h TypeNameHolder.h Unit.h Vec3.h DataFileList.o : DataFileList.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h PDBfile.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataFilter.o : DataFilter.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataFile.h DataFileList.h DataFilter.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_integer.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h GridBin.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO.o : DataIO.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataSet.h DataSetList.h DataSet_2D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_MatrixDbl.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h @@ -182,28 +172,24 @@ DataIO_CharmmFastRep.o : DataIO_CharmmFastRep.cpp ArgList.h AssociatedData.h Ato DataIO_CharmmOutput.o : DataIO_CharmmOutput.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_CharmmOutput.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_double.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_CharmmRepLog.o : DataIO_CharmmRepLog.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_CharmmRepLog.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_RemLog.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_CharmmRtfPrm.o : DataIO_CharmmRtfPrm.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharmmParamFile.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_CharmmRtfPrm.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Parameters.h DataSet_Topology.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -DataIO_Cmatrix.o : DataIO_Cmatrix.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h BaseIOtype.h Box.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Cmatrix.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Cmatrix_MEM.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h +DataIO_Cmatrix_Binary.o : DataIO_Cmatrix_Binary.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Cluster/Cframes.h Cluster/Cmatrix_Binary.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Cmatrix_Binary.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_PairwiseCache.h DataSet_PairwiseCache_MEM.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h +DataIO_Cmatrix_NC.o : DataIO_Cmatrix_NC.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Cluster/Cframes.h Cluster/Cmatrix_NC.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Cmatrix_NC.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_PairwiseCache.h DataSet_PairwiseCache_MEM.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Cpout.o : DataIO_Cpout.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h Cph.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Cpout.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_PHREMD.h DataSet_PHREMD_Explicit.h DataSet_PHREMD_Implicit.h DataSet_pH.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Evecs.o : DataIO_Evecs.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedFrame.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Evecs.h DataSet.h DataSetList.h DataSet_2D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_MatrixDbl.h DataSet_Modes.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Gnuplot.o : DataIO_Gnuplot.cpp ArgList.h Array1D.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Gnuplot.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Grace.o : DataIO_Grace.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Grace.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_double.h DataSet_string.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Mdout.o : DataIO_Mdout.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Mdout.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_double.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -DataIO_NC_Cmatrix.o : DataIO_NC_Cmatrix.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h BaseIOtype.h Box.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_NC_Cmatrix.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Cmatrix_MEM.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NC_Cmatrix.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_OpenDx.o : DataIO_OpenDx.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_OpenDx.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridDbl.h DataSet_GridFlt.h Dimension.h FileIO.h FileName.h Frame.h Grid.h GridBin.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Peaks.o : DataIO_Peaks.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Peaks.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Vector_Scalar.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_RemLog.o : DataIO_RemLog.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_RemLog.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_RemLog.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h -DataIO_Std.o : DataIO_Std.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h ClusterDist.h ClusterSieve.h ComplexArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Std.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Cmatrix.h DataSet_Cmatrix_MEM.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mat3x3.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Vector.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_string.h Dimension.h FileIO.h FileName.h Frame.h GridBin.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h +DataIO_Std.o : DataIO_Std.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Cluster/Cframes.h ComplexArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Std.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Mat3x3.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_PairwiseCache.h DataSet_PairwiseCache_MEM.h DataSet_Vector.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_string.h Dimension.h FileIO.h FileName.h Frame.h GridBin.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_VecTraj.o : DataIO_VecTraj.cpp ActionFrameCounter.h ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h ComplexArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_VecTraj.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_Vector.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ParmFile.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajectoryFile.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h DataIO_XVG.o : DataIO_XVG.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_XVG.h DataSet.h DataSetList.h DataSet_1D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_double.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataIO_Xplor.o : DataIO_Xplor.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h BufferedLine.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataIO.h DataIO_Xplor.h DataSet.h DataSetList.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_REF.h DataSet_GridFlt.h Dimension.h FileIO.h FileName.h Frame.h Grid.h GridBin.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ProgressBar.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataSet.o : DataSet.cpp AssociatedData.h CpptrajFile.h CpptrajStdio.h DataSet.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h Range.h TextFormat.h -DataSetList.o : DataSetList.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterSieve.h CompactFrameArray.h ComplexArray.h Constants.h CoordinateInfo.h Cph.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Cmatrix.h DataSet_Cmatrix_DISK.h DataSet_Cmatrix_MEM.h DataSet_Cmatrix_NOMEM.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_Coords_TRJ.h DataSet_GridDbl.h DataSet_GridFlt.h DataSet_Mat3x3.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Mesh.h DataSet_Modes.h DataSet_PHREMD.h DataSet_PHREMD_Explicit.h DataSet_PHREMD_Implicit.h DataSet_Parameters.h DataSet_RemLog.h DataSet_StringVar.h DataSet_Tensor.h DataSet_Topology.h DataSet_Vector.h DataSet_Vector_Scalar.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_integer_disk.h DataSet_integer_mem.h DataSet_pH.h DataSet_string.h DataSet_unsignedInt.h Dimension.h FileIO.h FileName.h Frame.h Grid.h GridBin.h Hungarian.h InputTrajCommon.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NC_Cmatrix.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h SymmetricTensor.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajFrameIndex.h Trajin.h TypeNameHolder.h Unit.h Vec3.h +DataSetList.o : DataSetList.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h AtomType.h Box.h Cluster/Cframes.h Cluster/Cmatrix_NC.h CompactFrameArray.h ComplexArray.h Constants.h CoordinateInfo.h Cph.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSetList.h DataSet_1D.h DataSet_2D.h DataSet_3D.h DataSet_Coords.h DataSet_Coords_CRD.h DataSet_Coords_REF.h DataSet_Coords_TRJ.h DataSet_GridDbl.h DataSet_GridFlt.h DataSet_Mat3x3.h DataSet_MatrixDbl.h DataSet_MatrixFlt.h DataSet_Mesh.h DataSet_Modes.h DataSet_PHREMD.h DataSet_PHREMD_Explicit.h DataSet_PHREMD_Implicit.h DataSet_PairwiseCache.h DataSet_PairwiseCache_MEM.h DataSet_PairwiseCache_NC.h DataSet_Parameters.h DataSet_RemLog.h DataSet_StringVar.h DataSet_Tensor.h DataSet_Topology.h DataSet_Vector.h DataSet_Vector_Scalar.h DataSet_double.h DataSet_float.h DataSet_integer.h DataSet_integer_disk.h DataSet_integer_mem.h DataSet_pH.h DataSet_string.h DataSet_unsignedInt.h Dimension.h FileIO.h FileName.h Frame.h Grid.h GridBin.h InputTrajCommon.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h Spline.h StringRoutines.h SymbolExporting.h SymmetricTensor.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h TrajFrameIndex.h Trajin.h TypeNameHolder.h Unit.h Vec3.h DataSet_1D.o : DataSet_1D.cpp ArrayIterator.h AssociatedData.h ComplexArray.h Constants.h Corr.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h PubFFT.h Range.h TextFormat.h DataSet_3D.o : DataSet_3D.cpp AssociatedData.h Box.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_3D.h Dimension.h FileIO.h FileName.h GridBin.h Matrix_3x3.h MetaData.h Parallel.h Range.h TextFormat.h Vec3.h -DataSet_Cmatrix.o : DataSet_Cmatrix.cpp ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -DataSet_Cmatrix_DISK.o : DataSet_Cmatrix_DISK.cpp ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Cmatrix_DISK.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NC_Cmatrix.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -DataSet_Cmatrix_MEM.o : DataSet_Cmatrix_MEM.cpp ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Cmatrix_MEM.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h -DataSet_Cmatrix_NOMEM.o : DataSet_Cmatrix_NOMEM.cpp ArrayIterator.h AssociatedData.h Atom.h AtomMap.h AtomMask.h AtomType.h Box.h ClusterDist.h ClusterSieve.h Constants.h CoordinateInfo.h CpptrajFile.h DataSet.h DataSet_1D.h DataSet_Cmatrix.h DataSet_Cmatrix_NOMEM.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h Hungarian.h MapAtom.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h SymmetricRmsdCalc.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataSet_Coords.o : DataSet_Coords.cpp AssociatedData.h Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_Coords.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataSet_Coords_CRD.o : DataSet_Coords_CRD.cpp AssociatedData.h Atom.h AtomMask.h AtomType.h Box.h CompactFrameArray.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_Coords.h DataSet_Coords_CRD.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h StringRoutines.h SymbolExporting.h TextFormat.h Topology.h TypeNameHolder.h Unit.h Vec3.h DataSet_Coords_REF.o : DataSet_Coords_REF.cpp ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h Frame.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Topology.h TrajFrameCounter.h Trajin.h Trajin_Single.h TypeNameHolder.h Unit.h Vec3.h @@ -217,6 +203,9 @@ DataSet_Mesh.o : DataSet_Mesh.cpp AssociatedData.h Constants.h CpptrajFile.h Cpp DataSet_Modes.o : DataSet_Modes.cpp ArgList.h ArrayIterator.h AssociatedData.h Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_2D.h DataSet_MatrixDbl.h DataSet_Modes.h Dimension.h FileIO.h FileName.h Frame.h MaskToken.h Matrix.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Unit.h Vec3.h DataSet_PHREMD_Explicit.o : DataSet_PHREMD_Explicit.cpp AssociatedData.h Cph.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_PHREMD.h DataSet_PHREMD_Explicit.h Dimension.h FileIO.h FileName.h MetaData.h NameType.h Parallel.h Range.h TextFormat.h DataSet_PHREMD_Implicit.o : DataSet_PHREMD_Implicit.cpp AssociatedData.h Cph.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_PHREMD.h DataSet_PHREMD_Implicit.h Dimension.h FileIO.h FileName.h MetaData.h NameType.h Parallel.h Range.h TextFormat.h +DataSet_PairwiseCache.o : DataSet_PairwiseCache.cpp AssociatedData.h Cluster/Cframes.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_PairwiseCache.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h Range.h TextFormat.h +DataSet_PairwiseCache_MEM.o : DataSet_PairwiseCache_MEM.cpp ArrayIterator.h AssociatedData.h Cluster/Cframes.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_PairwiseCache.h DataSet_PairwiseCache_MEM.h Dimension.h FileIO.h FileName.h Matrix.h MetaData.h Parallel.h Range.h StringRoutines.h TextFormat.h +DataSet_PairwiseCache_NC.o : DataSet_PairwiseCache_NC.cpp AssociatedData.h Cluster/Cframes.h Cluster/Cmatrix_NC.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_PairwiseCache.h DataSet_PairwiseCache_NC.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h Range.h StringRoutines.h TextFormat.h DataSet_Parameters.o : DataSet_Parameters.cpp AssociatedData.h AtomType.h Constants.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_Parameters.h Dimension.h FileIO.h FileName.h MetaData.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h TextFormat.h TypeNameHolder.h DataSet_RemLog.o : DataSet_RemLog.cpp AssociatedData.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_RemLog.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h Range.h ReplicaDimArray.h TextFormat.h DataSet_StringVar.o : DataSet_StringVar.cpp AssociatedData.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSet_StringVar.h Dimension.h FileIO.h FileName.h MetaData.h Parallel.h Range.h TextFormat.h @@ -335,7 +324,6 @@ MetaData.o : MetaData.cpp CpptrajStdio.h FileName.h MetaData.h Range.h StringRou Minimize_SteepestDescent.o : Minimize_SteepestDescent.cpp ActionFrameCounter.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h CharMask.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h EnergyArray.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Minimize_SteepestDescent.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h PotentialFunction.h PotentialTerm.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajectoryFile.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h Mol.o : Mol.cpp Atom.h AtomMask.h AtomType.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h FileName.h Frame.h MaskToken.h Matrix_3x3.h Mol.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Topology.h TypeNameHolder.h Unit.h Vec3.h Mol2File.o : Mol2File.cpp Atom.h CpptrajFile.h CpptrajStdio.h FileIO.h FileName.h Mol2File.h NameType.h Parallel.h Residue.h StringRoutines.h SymbolExporting.h -NC_Cmatrix.o : NC_Cmatrix.cpp CpptrajStdio.h FileName.h NC_Cmatrix.h NC_Routines.h NC_Routines.o : NC_Routines.cpp CpptrajStdio.h NC_Routines.h NameType.o : NameType.cpp CpptrajStdio.h NameType.h NetcdfFile.o : NetcdfFile.cpp Atom.h AtomMask.h Box.h Constants.h CoordinateInfo.h CpptrajStdio.h Frame.h MaskToken.h Matrix_3x3.h Molecule.h NC_Routines.h NameType.h NetcdfFile.h Parallel.h ParallelNetcdf.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h Unit.h Vec3.h Version.h @@ -433,5 +421,5 @@ Vec3.o : Vec3.cpp Constants.h CpptrajStdio.h Vec3.h ViewRst.o : ViewRst.cpp ActionFrameCounter.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h CpptrajFile.h CpptrajStdio.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h FileIO.h FileName.h FileTypes.h Frame.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h OutputTrajCommon.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h ParmFile.h Range.h ReferenceFrame.h ReplicaDimArray.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajectoryFile.h Trajout_Single.h TypeNameHolder.h Unit.h Vec3.h ViewRst.h main.o : main.cpp Action.h ActionList.h ActionState.h Analysis.h AnalysisList.h AnalysisState.h ArgList.h AssociatedData.h Atom.h AtomMask.h AtomType.h BaseIOtype.h Box.h Constants.h CoordinateInfo.h Cpptraj.h CpptrajFile.h CpptrajState.h DataFile.h DataFileList.h DataSet.h DataSetList.h DataSet_Coords.h DataSet_Coords_REF.h Dimension.h DispatchObject.h EnsembleIn.h EnsembleOutList.h FileIO.h FileName.h FileTypes.h Frame.h FramePtrArray.h InputTrajCommon.h MaskToken.h Matrix_3x3.h MetaData.h Molecule.h NameType.h Parallel.h ParameterHolders.h ParameterSet.h ParameterTypes.h Range.h ReferenceFrame.h ReplicaDimArray.h ReplicaInfo.h Residue.h Segment.h SymbolExporting.h TextFormat.h Timer.h Topology.h TrajFrameCounter.h Trajin.h TrajinList.h TrajoutList.h TypeNameHolder.h Unit.h Vec3.h molsurf.o : molsurf.c molsurf.h -vmdplugin/dtrplugin.o : vmdplugin/dtrplugin.cpp vmdplugin/../ByteRoutines.h vmdplugin/dtrplugin.hxx vmdplugin/vmddir.h +vmdplugin/dtrplugin.o : vmdplugin/dtrplugin.cpp ByteRoutines.h vmdplugin/dtrplugin.hxx vmdplugin/vmddir.h xoshiro128plusplus.o : xoshiro128plusplus.cpp diff --git a/src/cpptrajfiles b/src/cpptrajfiles index 4baa4ccc8c..e3befea6c9 100644 --- a/src/cpptrajfiles +++ b/src/cpptrajfiles @@ -149,17 +149,7 @@ COMMON_SOURCES= \ CharMask.cpp \ CharmmParamFile.cpp \ CIFfile.cpp \ - ClusterDist.cpp \ - ClusterList.cpp \ ClusterMap.cpp \ - ClusterMatrix.cpp \ - ClusterNode.cpp \ - ClusterSieve.cpp \ - Cluster_DBSCAN.cpp \ - Cluster_DPeaks.cpp \ - Cluster_HierAgglo.cpp \ - Cluster_Kmeans.cpp \ - Cluster_ReadInfo.cpp \ Cmd.cpp \ CmdInput.cpp \ CmdList.cpp \ @@ -183,7 +173,8 @@ COMMON_SOURCES= \ DataIO_CharmmOutput.cpp \ DataIO_CharmmRepLog.cpp \ DataIO_CharmmRtfPrm.cpp \ - DataIO_Cmatrix.cpp \ + DataIO_Cmatrix_Binary.cpp \ + DataIO_Cmatrix_NC.cpp \ DataIO_Cpout.cpp \ DataIO_Evecs.cpp \ DataIO_Gnuplot.cpp \ @@ -191,7 +182,6 @@ COMMON_SOURCES= \ DataIO_OpenDx.cpp \ DataIO_Peaks.cpp \ DataIO_Mdout.cpp \ - DataIO_NC_Cmatrix.cpp \ DataIO_RemLog.cpp \ DataIO_Std.cpp \ DataIO_VecTraj.cpp \ @@ -201,10 +191,6 @@ COMMON_SOURCES= \ DataSetList.cpp \ DataSet_1D.cpp \ DataSet_3D.cpp \ - DataSet_Cmatrix.cpp \ - DataSet_Cmatrix_DISK.cpp \ - DataSet_Cmatrix_MEM.cpp \ - DataSet_Cmatrix_NOMEM.cpp \ DataSet_Coords.cpp \ DataSet_Coords_CRD.cpp \ DataSet_Coords_REF.cpp \ @@ -216,6 +202,9 @@ COMMON_SOURCES= \ DataSet_MatrixFlt.cpp \ DataSet_Mesh.cpp \ DataSet_Modes.cpp \ + DataSet_PairwiseCache.cpp \ + DataSet_PairwiseCache_MEM.cpp \ + DataSet_PairwiseCache_NC.cpp \ DataSet_Parameters.cpp \ DataSet_pH.cpp \ DataSet_PHREMD_Explicit.cpp \ @@ -335,7 +324,6 @@ COMMON_SOURCES= \ Mol.cpp \ Mol2File.cpp \ NameType.cpp \ - NC_Cmatrix.cpp \ NC_Routines.cpp \ NetcdfFile.cpp \ OMM_helpers.cpp \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f87cbfea32..a508465422 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,11 +1,11 @@ -if(INSTALL_TESTS) - if(INSIDE_AMBER) - - # install to full path inside AmberTools directory - install(DIRECTORY . USE_SOURCE_PERMISSIONS DESTINATION AmberTools/src/cpptraj/test/ COMPONENT Tests) - else() +if(INSIDE_AMBER) + + # install to full path inside AmberTools directory + install(DIRECTORY . USE_SOURCE_PERMISSIONS DESTINATION AmberTools/src/cpptraj/test/ COMPONENT Tests ${TESTS_EXCLUDE_OPTION}) +else() + if(INSTALL_TESTS) # install to top-level dir install(DIRECTORY . USE_SOURCE_PERMISSIONS DESTINATION test/ COMPONENT Tests) endif() -endif() \ No newline at end of file +endif() diff --git a/test/Makefile b/test/Makefile index 90ede330a2..3bded85042 100644 --- a/test/Makefile +++ b/test/Makefile @@ -107,6 +107,10 @@ test.cluster: @-cd Test_Cluster_TrajWrites && ./RunTest.sh $(OPT) @-cd Test_Cluster_Dpeaks && ./RunTest.sh $(OPT) @-cd Test_Cluster_Nreps && ./RunTest.sh $(OPT) + @-cd Test_Cluster_AssignRefs && ./RunTest.sh $(OPT) + @-cd Test_Cluster_Cache && ./RunTest.sh $(OPT) + @-cd Test_Cluster_ReadInfo && ./RunTest.sh $(OPT) + @-cd Test_Cluster_CoordsAndData && ./RunTest.sh $(OPT) test.ired: @-cd Test_IRED && ./RunTest.sh $(OPT) diff --git a/test/Test_Cluster/RunTest.sh b/test/Test_Cluster/RunTest.sh index 27025e5e31..b5e9365527 100755 --- a/test/Test_Cluster/RunTest.sh +++ b/test/Test_Cluster/RunTest.sh @@ -6,65 +6,82 @@ # NOTE: CpptrajPairDist name defined in Action_Clustering.cpp CleanFiles cluster.in cnumvtime.dat avg.summary.dat summary.dat CpptrajPairDist \ cpop.agr summary2.dat Cmatrix.nccmatrix Cmatrix.cmatrix summary3.dat \ - normpop.agr normframe.agr cascii.dat.save cascii.dat pw.out + normpop.agr normframe.agr cascii.dat.save cascii.dat pw.out \ + cinfo.dat mysil.cluster.dat mysil.frame.dat cascii?.info TESTNAME='Hierarchical agglomerative clustering tests' -Requires netcdf +#Requires netcdf INPUT="-i cluster.in" # Test in-memory PW dist calc cat > cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < + 0 0.195931 + 1 0.449004 + 2 0.208799 + 3 0.250219 + 4 0.23464 + 5 0.148413 + 6 0.131294 + 7 0.58599 + 8 1 diff --git a/test/Test_Cluster/mysil.frame.dat.save b/test/Test_Cluster/mysil.frame.dat.save new file mode 100644 index 0000000000..e40f666188 --- /dev/null +++ b/test/Test_Cluster/mysil.frame.dat.save @@ -0,0 +1,119 @@ +#C0 Silhouette + 0 -0.135988 + 1 -0.0266746 + 2 -0.0167628 + 3 0.0609673 + 4 0.0649603 + 5 0.0835595 + 6 0.0853858 + 7 0.0877827 + 8 0.0945669 + 9 0.0981459 + 10 0.10935 + 11 0.11516 + 12 0.118742 + 13 0.139884 + 14 0.152028 + 15 0.152095 + 16 0.155938 + 17 0.16327 + 18 0.177433 + 19 0.185396 + 20 0.20837 + 21 0.210512 + 22 0.214755 + 23 0.223949 + 24 0.227854 + 25 0.242904 + 26 0.244027 + 27 0.244217 + 28 0.253302 + 29 0.261434 + 30 0.265653 + 31 0.266742 + 32 0.269781 + 33 0.274618 + 34 0.275536 + 35 0.281617 + 36 0.287468 + 37 0.291597 + 38 0.292651 + 39 0.298959 + 40 0.305413 + 41 0.307236 + 42 0.311688 + 43 0.314331 + 44 0.318642 + 45 0.320001 + 46 0.330269 + +#C1 Silhouette + 48 0.319039 + 49 0.319785 + 50 0.348833 + 51 0.358286 + 52 0.384205 + 53 0.397178 + 54 0.428314 + 55 0.441785 + 56 0.44628 + 57 0.446432 + 58 0.44892 + 59 0.465936 + 60 0.472731 + 61 0.473003 + 62 0.48261 + 63 0.486779 + 64 0.491815 + 65 0.493443 + 66 0.49616 + 67 0.496202 + 68 0.506839 + 69 0.523232 + 70 0.523974 + 71 0.524305 + +#C2 Silhouette + 73 -0.0273079 + 74 0.143221 + 75 0.143939 + 76 0.179135 + 77 0.198277 + 78 0.217643 + 79 0.240545 + 80 0.25015 + 81 0.253356 + 82 0.28631 + 83 0.291313 + 84 0.329007 + +#C3 Silhouette + 86 0.181779 + 87 0.183371 + 88 0.259752 + 89 0.264702 + 90 0.287487 + 91 0.32422 + +#C4 Silhouette + 93 0.0272266 + 94 0.176844 + 95 0.208565 + 96 0.353716 + 97 0.40685 + +#C5 Silhouette + 99 0.101416 + 100 0.195411 + +#C6 Silhouette + 102 0.100473 + 103 0.162116 + +#C7 Silhouette + 105 0.582066 + 106 0.589914 + +#C8 Silhouette + 108 1 + diff --git a/test/Test_Cluster_AssignRefs/RunTest.sh b/test/Test_Cluster_AssignRefs/RunTest.sh new file mode 100755 index 0000000000..bfee0907e0 --- /dev/null +++ b/test/Test_Cluster_AssignRefs/RunTest.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +. ../MasterTest.sh + +CleanFiles cluster.in summary.dat ksummary.dat PW + +INPUT='-i cluster.in' + +TESTNAME='Clustering, assign reference names' + +Requires netcdf + +cat > cluster.in <MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -5.7680 10.4340 3.1170 N3 1 SER 0.184900 + 2 H1 -6.6890 10.6870 2.7870 H 1 SER 0.189800 + 3 H2 -5.2100 10.0860 2.3510 H 1 SER 0.189800 + 4 H3 -5.9170 9.7590 3.8530 H 1 SER 0.189800 + 5 CA -5.2170 11.7130 3.5910 CT 1 SER 0.056700 + 6 HA -5.5610 12.4000 2.8180 HP 1 SER 0.078200 + 7 CB -5.8450 12.0530 4.9400 CT 1 SER 0.259600 + 8 HB2 -6.9150 12.0870 4.7360 H1 1 SER 0.027300 + 9 HB3 -5.6180 13.0490 5.3200 H1 1 SER 0.027300 + 10 OG -5.5110 11.0600 5.8830 OH 1 SER -0.671400 + 11 HG -6.3300 10.6260 6.1350 HO 1 SER 0.423900 + 12 C -3.7060 11.8100 3.4370 C 1 SER 0.616300 + 13 O -3.3060 12.2490 2.3610 O 1 SER -0.572200 + 14 N -2.8890 11.4250 4.4200 N 2 TRP -0.415700 + 15 H -3.3730 11.1220 5.2530 H 2 TRP 0.271900 + 16 CA -1.4410 11.4680 4.3780 CT 2 TRP -0.027500 + 17 HA -1.1200 12.5090 4.3350 H1 2 TRP 0.112300 + 18 CB -0.8390 10.9680 5.6890 CT 2 TRP -0.005000 + 19 HB2 -0.7480 9.8830 5.7170 HC 2 TRP 0.033900 + 20 HB3 -1.5230 11.0700 6.5310 HC 2 TRP 0.033900 + 21 CG 0.4410 11.6340 6.0770 C* 2 TRP -0.141500 + 22 CD1 0.6100 12.9490 6.3450 CW 2 TRP -0.163800 + 23 HD1 -0.2180 13.6410 6.3960 H4 2 TRP 0.206200 + 24 NE1 1.9110 13.2180 6.7220 NA 2 TRP -0.341800 + 25 HE1 2.3330 14.1120 6.9300 H 2 TRP 0.341200 + 26 CE2 2.6500 12.0530 6.7490 CN 2 TRP 0.138000 + 27 CZ2 3.9870 11.6890 6.9510 CA 2 TRP -0.260100 + 28 HZ2 4.6160 12.4930 7.3040 HA 2 TRP 0.157200 + 29 CH2 4.4970 10.4090 6.7040 CA 2 TRP -0.113400 + 30 HH2 5.5280 10.1210 6.8450 HA 2 TRP 0.141700 + 31 CZ3 3.6350 9.4970 6.0850 CA 2 TRP -0.197200 + 32 HZ3 4.0190 8.5000 5.9230 HA 2 TRP 0.144700 + 33 CE3 2.3010 9.8260 5.8150 CA 2 TRP -0.238700 + 34 HE3 1.6840 9.1240 5.2750 HA 2 TRP 0.170000 + 35 CD2 1.7820 11.0720 6.2020 CB 2 TRP 0.124300 + 36 C -0.8820 10.6490 3.2230 C 2 TRP 0.597300 + 37 O 0.0310 11.0690 2.5160 O 2 TRP -0.567900 + 38 N -1.5970 9.5630 2.9220 N 3 THR -0.415700 + 39 H -2.3560 9.3890 3.5640 H 3 THR 0.271900 + 40 CA -1.5410 8.6910 1.7660 CT 3 THR -0.038900 + 41 HA -0.5220 8.3100 1.6870 H1 3 THR 0.100700 + 42 CB -2.4230 7.4570 1.9280 CT 3 THR 0.365400 + 43 HB -2.5120 7.0290 0.9300 H1 3 THR 0.004300 + 44 CG2 -2.0380 6.4860 3.0410 CT 3 THR -0.243800 + 45 HG21 -1.0720 5.9940 2.9280 HC 3 THR 0.064200 + 46 HG22 -2.0180 6.9130 4.0440 HC 3 THR 0.064200 + 47 HG23 -2.7280 5.6480 3.1350 HC 3 THR 0.064200 + 48 OG1 -3.6970 7.8900 2.3500 OH 3 THR -0.676100 + 49 HG1 -4.2910 7.7360 1.6110 HO 3 THR 0.410200 + 50 C -1.8770 9.4800 0.5080 C 3 THR 0.597300 + 51 O -2.9820 10.0080 0.4010 O 3 THR -0.567900 + 52 N -0.9030 9.3930 -0.4000 N 4 TRP -0.415700 + 53 H -0.0320 8.9310 -0.1790 H 4 TRP 0.271900 + 54 CA -0.9970 9.9330 -1.7420 CT 4 TRP -0.027500 + 55 HA -1.8480 10.6150 -1.7660 H1 4 TRP 0.112300 + 56 CB 0.2150 10.8430 -1.9150 CT 4 TRP -0.005000 + 57 HB2 0.3570 11.0170 -2.9810 HC 4 TRP 0.033900 + 58 HB3 1.0680 10.1950 -1.7130 HC 4 TRP 0.033900 + 59 CG 0.3420 12.1760 -1.2490 C* 4 TRP -0.141500 + 60 CD1 1.1540 12.4320 -0.1990 CW 4 TRP -0.163800 + 61 HD1 1.7870 11.7020 0.2840 H4 4 TRP 0.206200 + 62 NE1 0.9020 13.7360 0.1810 NA 4 TRP -0.341800 + 63 HE1 1.3860 14.2190 0.9250 H 4 TRP 0.341200 + 64 CE2 -0.1300 14.3060 -0.5370 CN 4 TRP 0.138000 + 65 CZ2 -0.7270 15.5710 -0.4810 CA 4 TRP -0.260100 + 66 HZ2 -0.4800 16.3510 0.2240 HA 4 TRP 0.157200 + 67 CH2 -1.7280 15.9150 -1.3980 CA 4 TRP -0.113400 + 68 HH2 -2.2060 16.8780 -1.3010 HA 4 TRP 0.141700 + 69 CZ3 -2.1300 14.9430 -2.3220 CA 4 TRP -0.197200 + 70 HZ3 -2.7990 15.1900 -3.1340 HA 4 TRP 0.144700 + 71 CE3 -1.5630 13.6640 -2.3610 CA 4 TRP -0.238700 + 72 HE3 -1.8520 12.9920 -3.1560 HA 4 TRP 0.170000 + 73 CD2 -0.5560 13.3080 -1.4500 CB 4 TRP 0.124300 + 74 C -1.0960 8.8680 -2.8250 C 4 TRP 0.597300 + 75 O -1.9990 8.8000 -3.6560 O 4 TRP -0.567900 + 76 N -0.0670 8.0190 -2.7700 N 5 GLU -0.516300 + 77 H 0.4970 8.2320 -1.9590 H 5 GLU 0.293600 + 78 CA 0.0600 6.7790 -3.5090 CT 5 GLU 0.039700 + 79 HA -0.8150 6.7010 -4.1550 H1 5 GLU 0.110500 + 80 CB 1.3250 6.9460 -4.3460 CT 5 GLU 0.056000 + 81 HB2 2.1200 7.1130 -3.6190 HC 5 GLU -0.017300 + 82 HB3 1.2900 7.9260 -4.8230 HC 5 GLU -0.017300 + 83 CG 1.6200 5.6970 -5.1710 CT 5 GLU 0.013600 + 84 HG2 1.4980 4.7510 -4.6440 HC 5 GLU -0.042500 + 85 HG3 2.6830 5.7840 -5.3990 HC 5 GLU -0.042500 + 86 CD 0.8160 5.6470 -6.4620 C 5 GLU 0.805400 + 87 OE1 1.0220 6.3280 -7.4890 O2 5 GLU -0.818800 + 88 OE2 -0.1350 4.8350 -6.4720 O2 5 GLU -0.818800 + 89 C -0.0360 5.7160 -2.4240 C 5 GLU 0.536600 + 90 O 0.8510 5.2760 -1.6960 O 5 GLU -0.581900 + 91 N -1.2680 5.2040 -2.3750 N 6 ASN -0.415700 + 92 H -1.9860 5.5020 -3.0190 H 6 ASN 0.271900 + 93 CA -1.6160 4.0240 -1.6100 CT 6 ASN 0.014300 + 94 HA -1.1720 4.0370 -0.6140 H1 6 ASN 0.104800 + 95 CB -3.1320 4.0310 -1.4320 CT 6 ASN -0.204100 + 96 HB2 -3.4970 4.0470 -2.4580 HC 6 ASN 0.079700 + 97 HB3 -3.5210 4.9820 -1.0660 HC 6 ASN 0.079700 + 98 CG -3.7000 2.8730 -0.6250 C 6 ASN 0.713000 + 99 OD1 -4.2670 1.9110 -1.1390 O 6 ASN -0.593100 + 100 ND2 -3.4840 2.7780 0.6890 N 6 ASN -0.919100 + 101 HD21 -3.1550 3.5520 1.2480 H 6 ASN 0.419600 + 102 HD22 -3.8070 1.9470 1.1630 H 6 ASN 0.419600 + 103 C -1.1640 2.7860 -2.3720 C 6 ASN 0.597300 + 104 O -1.8380 2.2400 -3.2430 O 6 ASN -0.567900 + 105 N -0.1320 2.1570 -1.8050 N 7 GLY -0.415700 + 106 H 0.1600 2.6730 -0.9880 H 7 GLY 0.271900 + 107 CA 0.5120 0.9240 -2.2110 CT 7 GLY -0.025200 + 108 HA2 1.5560 1.0230 -1.9130 H1 7 GLY 0.069800 + 109 HA3 0.4250 0.7590 -3.2840 H1 7 GLY 0.069800 + 110 C -0.0830 -0.2610 -1.4630 C 7 GLY 0.597300 + 111 O -0.0740 -0.3160 -0.2350 O 7 GLY -0.567900 + 112 N -0.7670 -1.2020 -2.1170 N 8 LYS -0.347900 + 113 H -0.8010 -1.0940 -3.1200 H 8 LYS 0.274700 + 114 CA -1.3410 -2.4090 -1.5570 CT 8 LYS -0.240000 + 115 HA -1.7590 -2.2360 -0.5650 H1 8 LYS 0.142600 + 116 CB -2.4810 -2.9270 -2.4290 CT 8 LYS -0.009400 + 117 HB2 -3.3330 -2.2590 -2.2990 HC 8 LYS 0.036200 + 118 HB3 -2.8280 -3.8330 -1.9330 HC 8 LYS 0.036200 + 119 CG -2.1600 -2.8460 -3.9190 CT 8 LYS 0.018700 + 120 HG2 -1.2040 -3.3500 -4.0600 HC 8 LYS 0.010300 + 121 HG3 -2.0540 -1.8430 -4.3320 HC 8 LYS 0.010300 + 122 CD -3.2090 -3.6110 -4.7200 CT 8 LYS -0.047900 + 123 HD2 -3.0030 -3.4430 -5.7770 HC 8 LYS 0.062100 + 124 HD3 -4.1550 -3.1600 -4.4220 HC 8 LYS 0.062100 + 125 CE -3.0090 -5.0880 -4.3900 CT 8 LYS -0.014300 + 126 HE2 -3.0800 -5.2280 -3.3110 HP 8 LYS 0.113500 + 127 HE3 -2.0430 -5.3750 -4.8050 HP 8 LYS 0.113500 + 128 NZ -4.0800 -5.8820 -5.0100 N3 8 LYS -0.385400 + 129 HZ1 -5.0060 -5.6560 -4.6770 H 8 LYS 0.340000 + 130 HZ2 -4.0590 -5.8450 -6.0190 H 8 LYS 0.340000 + 131 HZ3 -3.8690 -6.8220 -4.7060 H 8 LYS 0.340000 + 132 C -0.2920 -3.4830 -1.3050 C 8 LYS 0.734100 + 133 O 0.2280 -4.0620 -2.2560 O 8 LYS -0.589400 + 134 N -0.0200 -3.8230 -0.0430 N 9 TRP -0.415700 + 135 H -0.2850 -3.2090 0.7140 H 9 TRP 0.271900 + 136 CA 0.8560 -4.9230 0.3080 CT 9 TRP -0.027500 + 137 HA 1.8370 -4.9390 -0.1660 H1 9 TRP 0.112300 + 138 CB 1.1430 -4.7920 1.8010 CT 9 TRP -0.005000 + 139 HB2 0.2210 -5.0000 2.3450 HC 9 TRP 0.033900 + 140 HB3 1.3580 -3.7590 2.0720 HC 9 TRP 0.033900 + 141 CG 2.0830 -5.7030 2.5230 C* 9 TRP -0.141500 + 142 CD1 1.8320 -7.0090 2.7650 CW 9 TRP -0.163800 + 143 HD1 0.9460 -7.5960 2.5700 H4 9 TRP 0.206200 + 144 NE1 2.8900 -7.5900 3.4350 NA 9 TRP -0.341800 + 145 HE1 2.8550 -8.5930 3.5500 H 9 TRP 0.341200 + 146 CE2 3.9510 -6.7180 3.5670 CN 9 TRP 0.138000 + 147 CZ2 5.1960 -6.8260 4.1990 CA 9 TRP -0.260100 + 148 HZ2 5.3980 -7.7270 4.7600 HA 9 TRP 0.157200 + 149 CH2 6.0340 -5.7080 4.2780 CA 9 TRP -0.113400 + 150 HH2 6.9090 -5.7020 4.9110 HA 9 TRP 0.141700 + 151 CZ3 5.5880 -4.5250 3.6760 CA 9 TRP -0.197200 + 152 HZ3 6.2870 -3.7020 3.6470 HA 9 TRP 0.144700 + 153 CE3 4.3470 -4.4410 3.0330 CA 9 TRP -0.238700 + 154 HE3 4.0750 -3.5250 2.5290 HA 9 TRP 0.170000 + 155 CD2 3.4310 -5.5050 3.0460 CB 9 TRP 0.124300 + 156 C 0.1650 -6.2320 -0.0470 C 9 TRP 0.597300 + 157 O -1.0370 -6.3080 0.2010 O 9 TRP -0.567900 + 158 N 0.8840 -7.1300 -0.7240 N 10 THR -0.415700 + 159 H 1.8070 -6.8430 -1.0180 H 10 THR 0.271900 + 160 CA 0.3460 -8.3310 -1.3280 CT 10 THR -0.038900 + 161 HA -0.6100 -8.5160 -0.8390 H1 10 THR 0.100700 + 162 CB 0.2750 -8.1170 -2.8380 CT 10 THR 0.365400 + 163 HB 1.2160 -7.8660 -3.3270 H1 10 THR 0.004300 + 164 CG2 -0.3610 -9.2840 -3.5880 CT 10 THR -0.243800 + 165 HG21 -1.1800 -9.7360 -3.0280 HC 10 THR 0.064200 + 166 HG22 -0.8760 -9.0010 -4.5070 HC 10 THR 0.064200 + 167 HG23 0.3590 -10.0640 -3.8360 HC 10 THR 0.064200 + 168 OG1 -0.5660 -7.0260 -3.1360 OH 10 THR -0.676100 + 169 HG1 0.0210 -6.2740 -3.0250 HO 10 THR 0.410200 + 170 C 1.1620 -9.5610 -0.9570 C 10 THR 0.597300 + 171 O 2.2220 -9.7590 -1.5460 O 10 THR -0.567900 + 172 N 0.6560 -10.2540 0.0660 N 11 TRP -0.415700 + 173 H -0.2660 -10.0060 0.3960 H 11 TRP 0.271900 + 174 CA 1.1910 -11.4720 0.6400 CT 11 TRP -0.027500 + 175 HA 2.2460 -11.5670 0.3850 H1 11 TRP 0.112300 + 176 CB 1.3110 -11.2320 2.1420 CT 11 TRP -0.005000 + 177 HB2 0.2700 -11.1970 2.4630 HC 11 TRP 0.033900 + 178 HB3 1.8110 -10.2740 2.2890 HC 11 TRP 0.033900 + 179 CG 1.8950 -12.3760 2.9070 C* 11 TRP -0.141500 + 180 CD1 3.2140 -12.6300 3.0600 CW 11 TRP -0.163800 + 181 HD1 4.0570 -12.1390 2.5960 H4 11 TRP 0.206200 + 182 NE1 3.3190 -13.7390 3.8750 NA 11 TRP -0.341800 + 183 HE1 4.1730 -14.0700 4.3010 H 11 TRP 0.341200 + 184 CE2 2.0820 -14.2310 4.2400 CN 11 TRP 0.138000 + 185 CZ2 1.8030 -15.4120 4.9360 CA 11 TRP -0.260100 + 186 HZ2 2.5820 -16.0610 5.3080 HA 11 TRP 0.157200 + 187 CH2 0.4450 -15.5890 5.2290 CA 11 TRP -0.113400 + 188 HH2 0.2520 -16.4990 5.7770 HA 11 TRP 0.141700 + 189 CZ3 -0.5600 -14.8160 4.6350 CA 11 TRP -0.197200 + 190 HZ3 -1.6070 -15.0200 4.8030 HA 11 TRP 0.144700 + 191 CE3 -0.2130 -13.7550 3.7910 CA 11 TRP -0.238700 + 192 HE3 -0.9710 -13.1570 3.3070 HA 11 TRP 0.170000 + 193 CD2 1.1250 -13.3440 3.6810 CB 11 TRP 0.124300 + 194 C 0.3370 -12.6620 0.2240 C 11 TRP 0.597300 + 195 O -0.8770 -12.6190 0.4050 O 11 TRP -0.567900 + 196 N 0.9500 -13.6170 -0.4780 N 12 LYS -0.347900 + 197 H 1.9480 -13.6320 -0.3190 H 12 LYS 0.274700 + 198 CA 0.2790 -14.8140 -0.9440 CT 12 LYS -0.240000 + 199 HA -0.7510 -14.8560 -0.5900 H1 12 LYS 0.142600 + 200 CB 0.4020 -14.8590 -2.4650 CT 12 LYS -0.009400 + 201 HB2 0.2670 -15.8930 -2.7820 HC 12 LYS 0.036200 + 202 HB3 1.3850 -14.4640 -2.7190 HC 12 LYS 0.036200 + 203 CG -0.5780 -13.9090 -3.1480 CT 12 LYS 0.018700 + 204 HG2 -0.5640 -12.9260 -2.6770 HC 12 LYS 0.010300 + 205 HG3 -1.6090 -14.2340 -3.0070 HC 12 LYS 0.010300 + 206 CD -0.2670 -13.5570 -4.6000 CT 12 LYS -0.047900 + 207 HD2 -0.1010 -14.4600 -5.1870 HC 12 LYS 0.062100 + 208 HD3 0.5910 -12.8870 -4.6450 HC 12 LYS 0.062100 + 209 CE -1.3450 -12.7450 -5.3120 CT 12 LYS -0.014300 + 210 HE2 -1.4320 -11.8940 -4.6370 HP 12 LYS 0.113500 + 211 HE3 -2.2710 -13.3190 -5.3100 HP 12 LYS 0.113500 + 212 NZ -1.1100 -12.5860 -6.7560 N3 12 LYS -0.385400 + 213 HZ1 -0.9600 -13.4400 -7.2740 H 12 LYS 0.340000 + 214 HZ2 -2.0070 -12.2490 -7.0720 H 12 LYS 0.340000 + 215 HZ3 -0.3280 -11.9840 -6.9710 H 12 LYS 0.340000 + 216 C 0.8700 -15.9860 -0.1750 C 12 LYS 0.734100 + 217 O 0.1830 -16.9850 0.0320 O 12 LYS -0.589400 + 218 N 2.1620 -15.9530 0.1590 N 13 NME -0.415700 + 219 H 2.7350 -15.3410 -0.4050 H 13 NME 0.271900 + 220 CH3 2.8770 -16.8200 1.0740 CT 13 NME -0.149000 + 221 HH31 2.1070 -17.4590 1.5050 H1 13 NME 0.097600 + 222 HH32 3.5630 -17.4610 0.5190 H1 13 NME 0.097600 + 223 HH33 3.5440 -16.1940 1.6670 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** diff --git a/test/Test_Cluster_AssignRefs/rep.c1.mol2 b/test/Test_Cluster_AssignRefs/rep.c1.mol2 new file mode 100644 index 0000000000..db6b80c7a6 --- /dev/null +++ b/test/Test_Cluster_AssignRefs/rep.c1.mol2 @@ -0,0 +1,476 @@ +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N 4.4660 8.8010 1.8900 N3 1 SER 0.184900 + 2 H1 4.6250 8.6600 0.9030 H 1 SER 0.189800 + 3 H2 4.4430 9.7710 2.1740 H 1 SER 0.189800 + 4 H3 5.2700 8.4320 2.3760 H 1 SER 0.189800 + 5 CA 3.2040 8.1010 2.1790 CT 1 SER 0.056700 + 6 HA 2.7370 8.4460 3.1010 HP 1 SER 0.078200 + 7 CB 2.1990 8.4150 1.0740 CT 1 SER 0.259600 + 8 HB2 1.1670 8.4100 1.4230 H1 1 SER 0.027300 + 9 HB3 2.1700 7.6890 0.2620 H1 1 SER 0.027300 + 10 OG 2.4790 9.7080 0.5860 OH 1 SER -0.671400 + 11 HG 1.9410 9.9820 -0.1600 HO 1 SER 0.423900 + 12 C 3.4160 6.6210 2.4620 C 1 SER 0.616300 + 13 O 4.2300 5.8860 1.9060 O 1 SER -0.572200 + 14 N 2.5780 6.0860 3.3530 N 2 TRP -0.415700 + 15 H 1.9780 6.7230 3.8580 H 2 TRP 0.271900 + 16 CA 2.5130 4.6450 3.4840 CT 2 TRP -0.027500 + 17 HA 3.4840 4.1500 3.4880 H1 2 TRP 0.112300 + 18 CB 1.8690 4.4600 4.8550 CT 2 TRP -0.005000 + 19 HB2 0.9400 5.0070 5.0130 HC 2 TRP 0.033900 + 20 HB3 2.4750 4.9610 5.6110 HC 2 TRP 0.033900 + 21 CG 1.7510 3.0010 5.1600 C* 2 TRP -0.141500 + 22 CD1 2.7240 2.1190 5.4840 CW 2 TRP -0.163800 + 23 HD1 3.7340 2.4420 5.2810 H4 2 TRP 0.206200 + 24 NE1 2.2640 0.8310 5.6750 NA 2 TRP -0.341800 + 25 HE1 2.8030 0.0090 5.9060 H 2 TRP 0.341200 + 26 CE2 0.8840 0.8540 5.6690 CN 2 TRP 0.138000 + 27 CZ2 -0.0690 -0.1440 5.9010 CA 2 TRP -0.260100 + 28 HZ2 0.2710 -1.0840 6.3100 HA 2 TRP 0.157200 + 29 CH2 -1.4090 0.2110 5.6990 CA 2 TRP -0.113400 + 30 HH2 -2.1340 -0.5550 5.9290 HA 2 TRP 0.141700 + 31 CZ3 -1.7940 1.4590 5.1960 CA 2 TRP -0.197200 + 32 HZ3 -2.8090 1.7290 4.9430 HA 2 TRP 0.144700 + 33 CE3 -0.7940 2.4030 4.9370 CA 2 TRP -0.238700 + 34 HE3 -1.0040 3.3890 4.5490 HA 2 TRP 0.170000 + 35 CD2 0.5620 2.1560 5.2040 CB 2 TRP 0.124300 + 36 C 1.7250 3.9640 2.3740 C 2 TRP 0.597300 + 37 O 2.2100 3.0080 1.7730 O 2 TRP -0.567900 + 38 N 0.5780 4.5190 1.9770 N 3 THR -0.415700 + 39 H 0.3090 5.3470 2.4900 H 3 THR 0.271900 + 40 CA -0.1220 4.2560 0.7360 CT 3 THR -0.038900 + 41 HA -0.3120 3.1910 0.6070 H1 3 THR 0.100700 + 42 CB -1.4170 5.0590 0.6500 CT 3 THR 0.365400 + 43 HB -1.7310 5.2730 -0.3720 H1 3 THR 0.004300 + 44 CG2 -2.6130 4.3430 1.2690 CT 3 THR -0.243800 + 45 HG21 -2.7530 3.3680 0.8000 HC 3 THR 0.064200 + 46 HG22 -2.4860 4.0490 2.3110 HC 3 THR 0.064200 + 47 HG23 -3.5950 4.8070 1.1810 HC 3 THR 0.064200 + 48 OG1 -1.3390 6.3190 1.2790 OH 3 THR -0.676100 + 49 HG1 -1.5650 7.0260 0.6710 HO 3 THR 0.410200 + 50 C 0.7030 4.7070 -0.4610 C 3 THR 0.597300 + 51 O 0.7630 5.8760 -0.8350 O 3 THR -0.567900 + 52 N 1.3350 3.7850 -1.1910 N 4 TRP -0.415700 + 53 H 1.0980 2.8180 -1.0250 H 4 TRP 0.271900 + 54 CA 2.0190 4.0290 -2.4450 CT 4 TRP -0.027500 + 55 HA 2.3080 5.0550 -2.6720 H1 4 TRP 0.112300 + 56 CB 3.3730 3.3260 -2.4210 CT 4 TRP -0.005000 + 57 HB2 3.8530 3.3280 -3.4000 HC 4 TRP 0.033900 + 58 HB3 3.2960 2.2780 -2.1300 HC 4 TRP 0.033900 + 59 CG 4.4140 3.9860 -1.5760 C* 4 TRP -0.141500 + 60 CD1 5.0650 3.4640 -0.5110 CW 4 TRP -0.163800 + 61 HD1 4.8750 2.4910 -0.0840 H4 4 TRP 0.206200 + 62 NE1 5.8530 4.4490 0.0500 NA 4 TRP -0.341800 + 63 HE1 6.3810 4.3770 0.9080 H 4 TRP 0.341200 + 64 CE2 5.8450 5.6220 -0.6770 CN 4 TRP 0.138000 + 65 CZ2 6.5060 6.8370 -0.4620 CA 4 TRP -0.260100 + 66 HZ2 7.2610 6.9370 0.3040 HA 4 TRP 0.157200 + 67 CH2 6.3560 7.7430 -1.5190 CA 4 TRP -0.113400 + 68 HH2 6.8730 8.6890 -1.4500 HA 4 TRP 0.141700 + 69 CZ3 5.3870 7.5360 -2.5080 CA 4 TRP -0.197200 + 70 HZ3 5.2070 8.3130 -3.2370 HA 4 TRP 0.144700 + 71 CE3 4.6370 6.3620 -2.6450 CA 4 TRP -0.238700 + 72 HE3 3.8860 6.3140 -3.4190 HA 4 TRP 0.170000 + 73 CD2 4.9260 5.3440 -1.7220 CB 4 TRP 0.124300 + 74 C 1.2120 3.7380 -3.7020 C 4 TRP 0.597300 + 75 O 1.3970 4.4290 -4.7010 O 4 TRP -0.567900 + 76 N 0.3370 2.7290 -3.7030 N 5 GLU -0.516300 + 77 H 0.3200 2.2370 -2.8210 H 5 GLU 0.293600 + 78 CA -0.6890 2.5260 -4.7050 CT 5 GLU 0.039700 + 79 HA -0.7680 3.2880 -5.4810 H1 5 GLU 0.110500 + 80 CB -0.4660 1.2140 -5.4530 CT 5 GLU 0.056000 + 81 HB2 -0.5670 0.3720 -4.7690 HC 5 GLU -0.017300 + 82 HB3 0.5610 1.2410 -5.8170 HC 5 GLU -0.017300 + 83 CG -1.3540 0.9950 -6.6750 CT 5 GLU 0.013600 + 84 HG2 -1.3740 1.8890 -7.3000 HC 5 GLU -0.042500 + 85 HG3 -2.3990 0.8270 -6.4180 HC 5 GLU -0.042500 + 86 CD -0.8860 -0.2020 -7.4900 C 5 GLU 0.805400 + 87 OE1 -0.3230 0.0470 -8.5780 O2 5 GLU -0.818800 + 88 OE2 -1.1820 -1.3860 -7.2210 O2 5 GLU -0.818800 + 89 C -2.0370 2.5730 -4.0010 C 5 GLU 0.536600 + 90 O -2.2720 1.7950 -3.0790 O 5 GLU -0.581900 + 91 N -2.9390 3.4990 -4.3370 N 6 ASN -0.415700 + 92 H -2.6310 4.0840 -5.1000 H 6 ASN 0.271900 + 93 CA -4.1510 3.8240 -3.6130 CT 6 ASN 0.014300 + 94 HA -4.0930 3.5760 -2.5530 H1 6 ASN 0.104800 + 95 CB -4.2820 5.3410 -3.7090 CT 6 ASN -0.204100 + 96 HB2 -4.1080 5.7460 -4.7050 HC 6 ASN 0.079700 + 97 HB3 -3.4210 5.7640 -3.1910 HC 6 ASN 0.079700 + 98 CG -5.4800 6.0090 -3.0480 C 6 ASN 0.713000 + 99 OD1 -6.2750 6.7910 -3.5650 O 6 ASN -0.593100 + 100 ND2 -5.8290 5.5710 -1.8360 N 6 ASN -0.919100 + 101 HD21 -5.0850 5.0760 -1.3650 H 6 ASN 0.419600 + 102 HD22 -6.5850 6.0770 -1.3980 H 6 ASN 0.419600 + 103 C -5.4020 3.1350 -4.1400 C 6 ASN 0.597300 + 104 O -5.8990 3.5230 -5.1940 O 6 ASN -0.567900 + 105 N -5.8410 2.1610 -3.3390 N 7 GLY -0.415700 + 106 H -5.4270 2.0090 -2.4300 H 7 GLY 0.271900 + 107 CA -7.2180 1.7460 -3.5160 CT 7 GLY -0.025200 + 108 HA2 -7.6260 1.8440 -4.5220 H1 7 GLY 0.069800 + 109 HA3 -7.8840 2.3810 -2.9320 H1 7 GLY 0.069800 + 110 C -7.4960 0.3350 -3.0180 C 7 GLY 0.597300 + 111 O -8.4700 0.1330 -2.2960 O 7 GLY -0.567900 + 112 N -6.7580 -0.7110 -3.3960 N 8 LYS -0.347900 + 113 H -6.0100 -0.4910 -4.0390 H 8 LYS 0.274700 + 114 CA -6.7760 -1.9160 -2.5920 CT 8 LYS -0.240000 + 115 HA -7.3320 -1.8000 -1.6610 H1 8 LYS 0.142600 + 116 CB -7.3460 -3.0990 -3.3680 CT 8 LYS -0.009400 + 117 HB2 -7.3800 -3.9040 -2.6340 HC 8 LYS 0.036200 + 118 HB3 -6.5730 -3.4890 -4.0300 HC 8 LYS 0.036200 + 119 CG -8.6890 -3.0210 -4.0890 CT 8 LYS 0.018700 + 120 HG2 -8.8180 -1.9880 -4.4130 HC 8 LYS 0.010300 + 121 HG3 -9.5180 -3.2420 -3.4170 HC 8 LYS 0.010300 + 122 CD -8.7980 -3.9240 -5.3140 CT 8 LYS -0.047900 + 123 HD2 -9.7980 -3.7440 -5.7090 HC 8 LYS 0.062100 + 124 HD3 -8.7300 -4.9540 -4.9630 HC 8 LYS 0.062100 + 125 CE -7.7990 -3.6760 -6.4410 CT 8 LYS -0.014300 + 126 HE2 -6.8900 -4.1350 -6.0540 HP 8 LYS 0.113500 + 127 HE3 -7.5840 -2.6090 -6.4870 HP 8 LYS 0.113500 + 128 NZ -8.2320 -4.2560 -7.7220 N3 8 LYS -0.385400 + 129 HZ1 -7.4650 -4.3100 -8.3770 H 8 LYS 0.340000 + 130 HZ2 -8.5850 -5.1930 -7.5910 H 8 LYS 0.340000 + 131 HZ3 -8.9800 -3.7150 -8.1330 H 8 LYS 0.340000 + 132 C -5.3840 -2.2310 -2.0610 C 8 LYS 0.734100 + 133 O -4.6200 -3.0590 -2.5510 O 8 LYS -0.589400 + 134 N -4.9460 -1.4820 -1.0460 N 9 TRP -0.415700 + 135 H -5.6090 -0.8800 -0.5790 H 9 TRP 0.271900 + 136 CA -3.6490 -1.5680 -0.4060 CT 9 TRP -0.027500 + 137 HA -2.9430 -1.9060 -1.1650 H1 9 TRP 0.112300 + 138 CB -3.2110 -0.2220 0.1650 CT 9 TRP -0.005000 + 139 HB2 -3.7510 0.1650 1.0290 HC 9 TRP 0.033900 + 140 HB3 -3.3370 0.5080 -0.6350 HC 9 TRP 0.033900 + 141 CG -1.8000 -0.0390 0.6240 C* 9 TRP -0.141500 + 142 CD1 -1.3600 0.1390 1.8910 CW 9 TRP -0.163800 + 143 HD1 -2.0580 0.2350 2.7100 H4 9 TRP 0.206200 + 144 NE1 0.0150 0.2560 1.9450 NA 9 TRP -0.341800 + 145 HE1 0.5980 0.2830 2.7690 H 9 TRP 0.341200 + 146 CE2 0.5170 0.1070 0.6680 CN 9 TRP 0.138000 + 147 CZ2 1.8030 -0.2170 0.2220 CA 9 TRP -0.260100 + 148 HZ2 2.6460 -0.1840 0.8960 HA 9 TRP 0.157200 + 149 CH2 2.0910 -0.4240 -1.1330 CA 9 TRP -0.113400 + 150 HH2 3.0680 -0.6020 -1.5580 HA 9 TRP 0.141700 + 151 CZ3 1.0150 -0.4360 -2.0280 CA 9 TRP -0.197200 + 152 HZ3 1.0650 -0.6640 -3.0820 HA 9 TRP 0.144700 + 153 CE3 -0.2950 -0.3490 -1.5400 CA 9 TRP -0.238700 + 154 HE3 -1.1130 -0.4940 -2.2300 HA 9 TRP 0.170000 + 155 CD2 -0.5940 -0.0790 -0.1950 CB 9 TRP 0.124300 + 156 C -3.5260 -2.6610 0.6460 C 9 TRP 0.597300 + 157 O -4.2080 -2.4600 1.6490 O 9 TRP -0.567900 + 158 N -2.7250 -3.7160 0.4820 N 10 THR -0.415700 + 159 H -2.1350 -3.9020 -0.3170 H 10 THR 0.271900 + 160 CA -2.5140 -4.6360 1.5810 CT 10 THR -0.038900 + 161 HA -2.8850 -4.1410 2.4780 H1 10 THR 0.100700 + 162 CB -3.2090 -5.9800 1.3780 CT 10 THR 0.365400 + 163 HB -2.5580 -6.5610 0.7250 H1 10 THR 0.004300 + 164 CG2 -3.3850 -6.8010 2.6520 CT 10 THR -0.243800 + 165 HG21 -2.3810 -6.8850 3.0670 HC 10 THR 0.064200 + 166 HG22 -4.0000 -6.2360 3.3520 HC 10 THR 0.064200 + 167 HG23 -3.8530 -7.7650 2.4490 HC 10 THR 0.064200 + 168 OG1 -4.5030 -5.7820 0.8560 OH 10 THR -0.676100 + 169 HG1 -4.4140 -5.9670 -0.0820 HO 10 THR 0.410200 + 170 C -1.0250 -4.8980 1.7510 C 10 THR 0.597300 + 171 O -0.4330 -5.5470 0.8910 O 10 THR -0.567900 + 172 N -0.4970 -4.4110 2.8760 N 11 TRP -0.415700 + 173 H -1.0890 -3.8420 3.4650 H 11 TRP 0.271900 + 174 CA 0.8540 -4.5590 3.3770 CT 11 TRP -0.027500 + 175 HA 1.4710 -4.8400 2.5230 H1 11 TRP 0.112300 + 176 CB 1.4200 -3.2160 3.8330 CT 11 TRP -0.005000 + 177 HB2 0.8900 -2.9050 4.7330 HC 11 TRP 0.033900 + 178 HB3 1.2170 -2.4440 3.0900 HC 11 TRP 0.033900 + 179 CG 2.9030 -3.2940 3.9990 C* 11 TRP -0.141500 + 180 CD1 3.8410 -3.3710 3.0280 CW 11 TRP -0.163800 + 181 HD1 3.5890 -3.2880 1.9810 H4 11 TRP 0.206200 + 182 NE1 5.1230 -3.2630 3.5300 NA 11 TRP -0.341800 + 183 HE1 5.9330 -3.1990 2.9310 H 11 TRP 0.341200 + 184 CE2 5.0340 -3.1180 4.9000 CN 11 TRP 0.138000 + 185 CZ2 5.9580 -2.9380 5.9360 CA 11 TRP -0.260100 + 186 HZ2 6.9960 -2.8640 5.6490 HA 11 TRP 0.157200 + 187 CH2 5.5920 -2.9750 7.2870 CA 11 TRP -0.113400 + 188 HH2 6.3030 -2.8560 8.0910 HA 11 TRP 0.141700 + 189 CZ3 4.2380 -3.1870 7.5710 CA 11 TRP -0.197200 + 190 HZ3 3.9050 -3.1250 8.5970 HA 11 TRP 0.144700 + 191 CE3 3.2520 -3.2960 6.5840 CA 11 TRP -0.238700 + 192 HE3 2.2210 -3.5630 6.7640 HA 11 TRP 0.170000 + 193 CD2 3.6600 -3.2020 5.2430 CB 11 TRP 0.124300 + 194 C 1.0690 -5.7390 4.3130 C 11 TRP 0.597300 + 195 O 0.2060 -6.1720 5.0740 O 11 TRP -0.567900 + 196 N 2.2860 -6.2600 4.1370 N 12 LYS -0.347900 + 197 H 2.8040 -5.9740 3.3190 H 12 LYS 0.274700 + 198 CA 2.6640 -7.5870 4.5800 CT 12 LYS -0.240000 + 199 HA 1.8450 -8.2380 4.8870 H1 12 LYS 0.142600 + 200 CB 3.3260 -8.3710 3.4510 CT 12 LYS -0.009400 + 201 HB2 3.7370 -9.3090 3.8250 HC 12 LYS 0.036200 + 202 HB3 4.1770 -7.8600 3.0000 HC 12 LYS 0.036200 + 203 CG 2.3520 -8.7420 2.3370 CT 12 LYS 0.018700 + 204 HG2 1.9420 -7.8550 1.8530 HC 12 LYS 0.010300 + 205 HG3 1.6000 -9.3930 2.7820 HC 12 LYS 0.010300 + 206 CD 2.9880 -9.4270 1.1300 CT 12 LYS -0.047900 + 207 HD2 3.5610 -10.2580 1.5390 HC 12 LYS 0.062100 + 208 HD3 3.7070 -8.7520 0.6660 HC 12 LYS 0.062100 + 209 CE 1.8420 -9.7750 0.1840 CT 12 LYS -0.014300 + 210 HE2 1.2930 -8.8880 -0.1330 HP 12 LYS 0.113500 + 211 HE3 1.1780 -10.4020 0.7770 HP 12 LYS 0.113500 + 212 NZ 2.3420 -10.5060 -0.9900 N3 12 LYS -0.385400 + 213 HZ1 1.5910 -10.9180 -1.5250 H 12 LYS 0.340000 + 214 HZ2 2.8560 -9.8710 -1.5840 H 12 LYS 0.340000 + 215 HZ3 2.9500 -11.1870 -0.5580 H 12 LYS 0.340000 + 216 C 3.6240 -7.5520 5.7600 C 12 LYS 0.734100 + 217 O 3.2280 -7.6610 6.9190 O 12 LYS -0.589400 + 218 N 4.8650 -7.1570 5.4680 N 13 NME -0.415700 + 219 H 5.0840 -6.9390 4.5060 H 13 NME 0.271900 + 220 CH3 5.8420 -6.6940 6.4310 CT 13 NME -0.149000 + 221 HH31 6.5130 -7.4980 6.7320 H1 13 NME 0.097600 + 222 HH32 6.4650 -5.9170 5.9880 H1 13 NME 0.097600 + 223 HH33 5.3300 -6.2820 7.3010 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** diff --git a/test/Test_Cluster_AssignRefs/rep.c2.mol2 b/test/Test_Cluster_AssignRefs/rep.c2.mol2 new file mode 100644 index 0000000000..bb5097a216 --- /dev/null +++ b/test/Test_Cluster_AssignRefs/rep.c2.mol2 @@ -0,0 +1,476 @@ +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N 2.5680 12.3590 0.0930 N3 1 SER 0.184900 + 2 H1 2.4520 12.6480 1.0530 H 1 SER 0.189800 + 3 H2 3.4390 11.8470 0.1050 H 1 SER 0.189800 + 4 H3 2.4940 13.1000 -0.5900 H 1 SER 0.189800 + 5 CA 1.4740 11.4380 -0.2520 CT 1 SER 0.056700 + 6 HA 0.5820 12.0120 -0.5030 HP 1 SER 0.078200 + 7 CB 1.7870 10.6040 -1.4910 CT 1 SER 0.259600 + 8 HB2 1.0770 9.8150 -1.7390 H1 1 SER 0.027300 + 9 HB3 2.7160 10.0330 -1.5030 H1 1 SER 0.027300 + 10 OG 1.8050 11.5120 -2.5700 OH 1 SER -0.671400 + 11 HG 1.2410 11.1920 -3.2780 HO 1 SER 0.423900 + 12 C 1.1340 10.4410 0.8460 C 1 SER 0.616300 + 13 O 1.9210 9.5780 1.2290 O 1 SER -0.572200 + 14 N -0.1100 10.5190 1.3250 N 2 TRP -0.415700 + 15 H -0.7350 11.2130 0.9400 H 2 TRP 0.271900 + 16 CA -0.6210 9.6270 2.3460 CT 2 TRP -0.027500 + 17 HA 0.0680 9.6450 3.1910 H1 2 TRP 0.112300 + 18 CB -1.9560 10.1840 2.8310 CT 2 TRP -0.005000 + 19 HB2 -2.6630 10.2240 2.0020 HC 2 TRP 0.033900 + 20 HB3 -1.7570 11.1740 3.2440 HC 2 TRP 0.033900 + 21 CG -2.6340 9.3750 3.8900 C* 2 TRP -0.141500 + 22 CD1 -2.1450 8.5630 4.8540 CW 2 TRP -0.163800 + 23 HD1 -1.0930 8.3340 4.9420 H4 2 TRP 0.206200 + 24 NE1 -3.1320 8.0540 5.6750 NA 2 TRP -0.341800 + 25 HE1 -2.8540 7.5250 6.4890 H 2 TRP 0.341200 + 26 CE2 -4.3440 8.5330 5.2200 CN 2 TRP 0.138000 + 27 CZ2 -5.6430 8.3300 5.7010 CA 2 TRP -0.260100 + 28 HZ2 -5.7890 7.7550 6.6040 HA 2 TRP 0.157200 + 29 CH2 -6.7130 9.0640 5.1760 CA 2 TRP -0.113400 + 30 HH2 -7.7210 8.8180 5.4770 HA 2 TRP 0.141700 + 31 CZ3 -6.4910 9.9980 4.1570 CA 2 TRP -0.197200 + 32 HZ3 -7.3930 10.4420 3.7620 HA 2 TRP 0.144700 + 33 CE3 -5.2020 10.0560 3.6140 CA 2 TRP -0.238700 + 34 HE3 -5.1840 10.4400 2.6050 HA 2 TRP 0.170000 + 35 CD2 -4.0720 9.4070 4.1360 CB 2 TRP 0.124300 + 36 C -0.7150 8.1530 1.9820 C 2 TRP 0.597300 + 37 O -0.2180 7.2160 2.6030 O 2 TRP -0.567900 + 38 N -1.2340 7.9240 0.7730 N 3 THR -0.415700 + 39 H -1.5800 8.6950 0.2190 H 3 THR 0.271900 + 40 CA -1.3990 6.6510 0.1020 CT 3 THR -0.038900 + 41 HA -0.9170 5.8440 0.6530 H1 3 THR 0.100700 + 42 CB -2.8700 6.2770 -0.0560 CT 3 THR 0.365400 + 43 HB -3.0300 5.4690 -0.7700 H1 3 THR 0.004300 + 44 CG2 -3.5410 5.8570 1.2480 CT 3 THR -0.243800 + 45 HG21 -3.8090 6.7030 1.8800 HC 3 THR 0.064200 + 46 HG22 -4.4430 5.2690 1.0770 HC 3 THR 0.064200 + 47 HG23 -2.7990 5.3080 1.8280 HC 3 THR 0.064200 + 48 OG1 -3.6900 7.3330 -0.5060 OH 3 THR -0.676100 + 49 HG1 -3.2660 7.8240 -1.2130 HO 3 THR 0.410200 + 50 C -0.6630 6.6690 -1.2300 C 3 THR 0.597300 + 51 O -1.2490 7.0580 -2.2380 O 3 THR -0.567900 + 52 N 0.5790 6.1830 -1.1700 N 4 TRP -0.415700 + 53 H 0.9870 5.9260 -0.2820 H 4 TRP 0.271900 + 54 CA 1.3900 5.9670 -2.3510 CT 4 TRP -0.027500 + 55 HA 1.2890 6.8610 -2.9660 H1 4 TRP 0.112300 + 56 CB 2.8500 5.7490 -1.9670 CT 4 TRP -0.005000 + 57 HB2 2.9260 4.8660 -1.3310 HC 4 TRP 0.033900 + 58 HB3 3.2520 6.6210 -1.4510 HC 4 TRP 0.033900 + 59 CG 3.6850 5.4910 -3.1800 C* 4 TRP -0.141500 + 60 CD1 4.0950 6.5170 -3.9590 CW 4 TRP -0.163800 + 61 HD1 3.9800 7.5810 -3.8150 H4 4 TRP 0.206200 + 62 NE1 4.9450 6.0410 -4.9390 NA 4 TRP -0.341800 + 63 HE1 5.2850 6.6710 -5.6510 H 4 TRP 0.341200 + 64 CE2 4.9670 4.6610 -4.9620 CN 4 TRP 0.138000 + 65 CZ2 5.4360 3.6970 -5.8630 CA 4 TRP -0.260100 + 66 HZ2 5.9280 3.9440 -6.7920 HA 4 TRP 0.157200 + 67 CH2 5.2070 2.3460 -5.5760 CA 4 TRP -0.113400 + 68 HH2 5.4960 1.6060 -6.3090 HA 4 TRP 0.141700 + 69 CZ3 4.6420 1.9950 -4.3450 CA 4 TRP -0.197200 + 70 HZ3 4.3290 0.9730 -4.1840 HA 4 TRP 0.144700 + 71 CE3 4.1900 2.9490 -3.4250 CA 4 TRP -0.238700 + 72 HE3 3.6870 2.5960 -2.5370 HA 4 TRP 0.170000 + 73 CD2 4.3250 4.3090 -3.7460 CB 4 TRP 0.124300 + 74 C 0.9310 4.8060 -3.2220 C 4 TRP 0.597300 + 75 O 0.9250 4.9430 -4.4440 O 4 TRP -0.567900 + 76 N 0.6050 3.7060 -2.5400 N 5 GLU -0.516300 + 77 H 0.7070 3.7410 -1.5360 H 5 GLU 0.293600 + 78 CA -0.3310 2.7250 -3.0490 CT 5 GLU 0.039700 + 79 HA -0.3320 2.9730 -4.1110 H1 5 GLU 0.110500 + 80 CB 0.2620 1.3700 -2.6720 CT 5 GLU 0.056000 + 81 HB2 -0.2040 1.0320 -1.7470 HC 5 GLU -0.017300 + 82 HB3 1.3510 1.3380 -2.6300 HC 5 GLU -0.017300 + 83 CG -0.1270 0.3600 -3.7480 CT 5 GLU 0.013600 + 84 HG2 0.2170 0.8280 -4.6700 HC 5 GLU -0.042500 + 85 HG3 -1.2030 0.2020 -3.8110 HC 5 GLU -0.042500 + 86 CD 0.4760 -1.0240 -3.5570 C 5 GLU 0.805400 + 87 OE1 1.6160 -1.1670 -4.0500 O2 5 GLU -0.818800 + 88 OE2 -0.1930 -1.8730 -2.9290 O2 5 GLU -0.818800 + 89 C -1.7420 2.9050 -2.5070 C 5 GLU 0.536600 + 90 O -1.9210 3.0310 -1.2980 O 5 GLU -0.581900 + 91 N -2.6790 3.1430 -3.4280 N 6 ASN -0.415700 + 92 H -2.5920 2.8810 -4.3990 H 6 ASN 0.271900 + 93 CA -4.0650 3.4410 -3.1260 CT 6 ASN 0.014300 + 94 HA -3.9240 4.1410 -2.3030 H1 6 ASN 0.104800 + 95 CB -4.6650 4.2250 -4.2900 CT 6 ASN -0.204100 + 96 HB2 -5.3610 3.5720 -4.8190 HC 6 ASN 0.079700 + 97 HB3 -3.8970 4.6230 -4.9520 HC 6 ASN 0.079700 + 98 CG -5.4840 5.4210 -3.8260 C 6 ASN 0.713000 + 99 OD1 -6.2700 5.3410 -2.8850 O 6 ASN -0.593100 + 100 ND2 -5.3640 6.6030 -4.4350 N 6 ASN -0.919100 + 101 HD21 -4.7420 6.7100 -5.2240 H 6 ASN 0.419600 + 102 HD22 -5.7640 7.4310 -4.0170 H 6 ASN 0.419600 + 103 C -4.7510 2.2190 -2.5330 C 6 ASN 0.597300 + 104 O -4.3910 1.0670 -2.7640 O 6 ASN -0.567900 + 105 N -5.7230 2.5060 -1.6640 N 7 GLY -0.415700 + 106 H -5.8760 3.4590 -1.3680 H 7 GLY 0.271900 + 107 CA -6.5190 1.4880 -1.0070 CT 7 GLY -0.025200 + 108 HA2 -7.0480 0.8370 -1.7030 H1 7 GLY 0.069800 + 109 HA3 -7.2680 1.9040 -0.3330 H1 7 GLY 0.069800 + 110 C -5.6480 0.5550 -0.1790 C 7 GLY 0.597300 + 111 O -4.8170 1.0730 0.5640 O 7 GLY -0.567900 + 112 N -5.7610 -0.7740 -0.2370 N 8 LYS -0.347900 + 113 H -6.5070 -1.1000 -0.8340 H 8 LYS 0.274700 + 114 CA -5.1460 -1.7160 0.6770 CT 8 LYS -0.240000 + 115 HA -5.1270 -1.3090 1.6880 H1 8 LYS 0.142600 + 116 CB -6.0850 -2.9180 0.6270 CT 8 LYS -0.009400 + 117 HB2 -5.5930 -3.7470 1.1380 HC 8 LYS 0.036200 + 118 HB3 -6.3050 -3.1020 -0.4240 HC 8 LYS 0.036200 + 119 CG -7.4230 -2.7380 1.3370 CT 8 LYS 0.018700 + 120 HG2 -7.9280 -1.9520 0.7750 HC 8 LYS 0.010300 + 121 HG3 -7.2810 -2.3880 2.3590 HC 8 LYS 0.010300 + 122 CD -8.2550 -4.0080 1.1840 CT 8 LYS -0.047900 + 123 HD2 -7.9580 -4.6940 1.9770 HC 8 LYS 0.062100 + 124 HD3 -8.0580 -4.4660 0.2150 HC 8 LYS 0.062100 + 125 CE -9.7430 -3.7230 1.3700 CT 8 LYS -0.014300 + 126 HE2 -10.0110 -3.1490 0.4830 HP 8 LYS 0.113500 + 127 HE3 -9.8560 -3.0290 2.2020 HP 8 LYS 0.113500 + 128 NZ -10.5970 -4.9150 1.4860 N3 8 LYS -0.385400 + 129 HZ1 -11.5440 -4.6690 1.2360 H 8 LYS 0.340000 + 130 HZ2 -10.1950 -5.5770 0.8390 H 8 LYS 0.340000 + 131 HZ3 -10.5230 -5.3640 2.3880 H 8 LYS 0.340000 + 132 C -3.7030 -2.1350 0.4330 C 8 LYS 0.734100 + 133 O -3.3980 -2.5010 -0.6990 O 8 LYS -0.589400 + 134 N -2.8370 -2.1440 1.4500 N 9 TRP -0.415700 + 135 H -3.2660 -1.8890 2.3280 H 9 TRP 0.271900 + 136 CA -1.4700 -2.6120 1.3410 CT 9 TRP -0.027500 + 137 HA -0.9110 -2.4110 0.4270 H1 9 TRP 0.112300 + 138 CB -0.6970 -1.8800 2.4340 CT 9 TRP -0.005000 + 139 HB2 -1.1700 -2.2050 3.3600 HC 9 TRP 0.033900 + 140 HB3 -0.7590 -0.7960 2.3390 HC 9 TRP 0.033900 + 141 CG 0.7540 -2.1150 2.7070 C* 9 TRP -0.141500 + 142 CD1 1.3100 -2.4420 3.8960 CW 9 TRP -0.163800 + 143 HD1 0.7430 -2.4140 4.8140 H4 9 TRP 0.206200 + 144 NE1 2.6710 -2.6170 3.7440 NA 9 TRP -0.341800 + 145 HE1 3.2160 -2.8110 4.5720 H 9 TRP 0.341200 + 146 CE2 3.0490 -2.2770 2.4610 CN 9 TRP 0.138000 + 147 CZ2 4.3240 -2.3840 1.8930 CA 9 TRP -0.260100 + 148 HZ2 5.2410 -2.5570 2.4360 HA 9 TRP 0.157200 + 149 CH2 4.4740 -2.0090 0.5520 CA 9 TRP -0.113400 + 150 HH2 5.5070 -1.9800 0.2390 HA 9 TRP 0.141700 + 151 CZ3 3.3440 -1.6840 -0.2070 CA 9 TRP -0.197200 + 152 HZ3 3.4230 -1.5230 -1.2720 HA 9 TRP 0.144700 + 153 CE3 2.0780 -1.7830 0.3830 CA 9 TRP -0.238700 + 154 HE3 1.2270 -1.5610 -0.2430 HA 9 TRP 0.170000 + 155 CD2 1.8470 -2.0440 1.7430 CB 9 TRP 0.124300 + 156 C -1.3820 -4.1250 1.4810 C 9 TRP 0.597300 + 157 O -1.3300 -4.6880 2.5720 O 9 TRP -0.567900 + 158 N -1.5080 -4.8160 0.3460 N 10 THR -0.415700 + 159 H -1.4630 -4.3840 -0.5660 H 10 THR 0.271900 + 160 CA -1.1440 -6.2190 0.3410 CT 10 THR -0.038900 + 161 HA -1.8110 -6.7080 1.0500 H1 10 THR 0.100700 + 162 CB -1.3370 -6.9320 -0.9940 CT 10 THR 0.365400 + 163 HB -1.0100 -7.9700 -0.9320 H1 10 THR 0.004300 + 164 CG2 -2.8370 -6.9880 -1.2690 CT 10 THR -0.243800 + 165 HG21 -3.0490 -5.9310 -1.4260 HC 10 THR 0.064200 + 166 HG22 -3.0930 -7.4340 -2.2300 HC 10 THR 0.064200 + 167 HG23 -3.2920 -7.4700 -0.4030 HC 10 THR 0.064200 + 168 OG1 -0.6650 -6.3420 -2.0850 OH 10 THR -0.676100 + 169 HG1 -1.0290 -6.7400 -2.8800 HO 10 THR 0.410200 + 170 C 0.2210 -6.5310 0.9390 C 10 THR 0.597300 + 171 O 1.2720 -6.1100 0.4610 O 10 THR -0.567900 + 172 N 0.1500 -7.2510 2.0610 N 11 TRP -0.415700 + 173 H -0.7370 -7.5370 2.4510 H 11 TRP 0.271900 + 174 CA 1.2940 -7.9120 2.6540 CT 11 TRP -0.027500 + 175 HA 1.8970 -7.0870 3.0340 H1 11 TRP 0.112300 + 176 CB 0.7440 -8.6050 3.8970 CT 11 TRP -0.005000 + 177 HB2 0.3160 -9.5760 3.6490 HC 11 TRP 0.033900 + 178 HB3 -0.0950 -8.0490 4.3160 HC 11 TRP 0.033900 + 179 CG 1.7590 -8.8560 4.9660 C* 11 TRP -0.141500 + 180 CD1 2.1020 -7.9870 5.9430 CW 11 TRP -0.163800 + 181 HD1 1.6360 -7.0200 6.0620 H4 11 TRP 0.206200 + 182 NE1 3.2700 -8.4370 6.5260 NA 11 TRP -0.341800 + 183 HE1 3.6120 -8.1090 7.4180 H 11 TRP 0.341200 + 184 CE2 3.6120 -9.6990 6.0830 CN 11 TRP 0.138000 + 185 CZ2 4.4720 -10.7340 6.4680 CA 11 TRP -0.260100 + 186 HZ2 5.1160 -10.8350 7.3300 HA 11 TRP 0.157200 + 187 CH2 4.5160 -11.9490 5.7740 CA 11 TRP -0.113400 + 188 HH2 5.2680 -12.6640 6.0730 HA 11 TRP 0.141700 + 189 CZ3 3.6270 -12.2020 4.7220 CA 11 TRP -0.197200 + 190 HZ3 3.6240 -13.0850 4.1010 HA 11 TRP 0.144700 + 191 CE3 2.7960 -11.1600 4.2940 CA 11 TRP -0.238700 + 192 HE3 2.1260 -11.4320 3.4920 HA 11 TRP 0.170000 + 193 CD2 2.7060 -9.9640 5.0230 CB 11 TRP 0.124300 + 194 C 2.2050 -8.7470 1.7660 C 11 TRP 0.597300 + 195 O 1.7170 -9.7200 1.1960 O 11 TRP -0.567900 + 196 N 3.4990 -8.4290 1.8490 N 12 LYS -0.347900 + 197 H 3.7020 -7.5930 2.3770 H 12 LYS 0.274700 + 198 CA 4.5550 -9.1850 1.2060 CT 12 LYS -0.240000 + 199 HA 4.1150 -9.8690 0.4800 H1 12 LYS 0.142600 + 200 CB 5.4900 -8.1870 0.5290 CT 12 LYS -0.009400 + 201 HB2 6.2940 -8.8110 0.1400 HC 12 LYS 0.036200 + 202 HB3 5.7640 -7.3570 1.1810 HC 12 LYS 0.036200 + 203 CG 4.7910 -7.5370 -0.6610 CT 12 LYS 0.018700 + 204 HG2 3.9210 -7.0310 -0.2420 HC 12 LYS 0.010300 + 205 HG3 4.5470 -8.3270 -1.3710 HC 12 LYS 0.010300 + 206 CD 5.6030 -6.4730 -1.3950 CT 12 LYS -0.047900 + 207 HD2 5.6910 -5.6540 -0.6820 HC 12 LYS 0.062100 + 208 HD3 4.9000 -6.1680 -2.1710 HC 12 LYS 0.062100 + 209 CE 6.9770 -6.9350 -1.8700 CT 12 LYS -0.014300 + 210 HE2 6.8710 -7.8940 -2.3760 HP 12 LYS 0.113500 + 211 HE3 7.5210 -7.2920 -0.9950 HP 12 LYS 0.113500 + 212 NZ 7.6300 -5.9360 -2.7310 N3 12 LYS -0.385400 + 213 HZ1 7.1600 -5.9920 -3.6230 H 12 LYS 0.340000 + 214 HZ2 7.7390 -5.0680 -2.2270 H 12 LYS 0.340000 + 215 HZ3 8.5080 -6.2730 -3.0990 H 12 LYS 0.340000 + 216 C 5.3320 -10.1440 2.0970 C 12 LYS 0.734100 + 217 O 5.3550 -11.2770 1.6220 O 12 LYS -0.589400 + 218 N 5.8320 -9.7320 3.2630 N 13 NME -0.415700 + 219 H 5.5630 -8.7890 3.5060 H 13 NME 0.271900 + 220 CH3 6.9330 -10.2970 4.0170 CT 13 NME -0.149000 + 221 HH31 7.7560 -9.5830 3.9870 H1 13 NME 0.097600 + 222 HH32 6.7090 -10.3500 5.0820 H1 13 NME 0.097600 + 223 HH33 7.4080 -11.1820 3.5940 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** diff --git a/test/Test_Cluster_AssignRefs/rep.c3.mol2 b/test/Test_Cluster_AssignRefs/rep.c3.mol2 new file mode 100644 index 0000000000..0671ae0863 --- /dev/null +++ b/test/Test_Cluster_AssignRefs/rep.c3.mol2 @@ -0,0 +1,476 @@ +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -1.6840 5.3290 4.3870 N3 1 SER 0.184900 + 2 H1 -1.2140 5.1190 3.5180 H 1 SER 0.189800 + 3 H2 -2.1480 4.4620 4.6130 H 1 SER 0.189800 + 4 H3 -2.3450 6.0920 4.4250 H 1 SER 0.189800 + 5 CA -0.6640 5.7090 5.3760 CT 1 SER 0.056700 + 6 HA -1.0940 6.0860 6.3040 HP 1 SER 0.078200 + 7 CB 0.1940 4.6200 6.0140 CT 1 SER 0.259600 + 8 HB2 -0.5270 4.0790 6.6260 H1 1 SER 0.027300 + 9 HB3 0.9280 5.1670 6.6050 H1 1 SER 0.027300 + 10 OG 0.7860 3.7450 5.0800 OH 1 SER -0.671400 + 11 HG 1.1870 3.0700 5.6330 HO 1 SER 0.423900 + 12 C 0.2410 6.7600 4.7490 C 1 SER 0.616300 + 13 O -0.1020 7.9360 4.8530 O 1 SER -0.572200 + 14 N 1.3630 6.4020 4.1210 N 2 TRP -0.415700 + 15 H 1.5020 5.4040 4.0570 H 2 TRP 0.271900 + 16 CA 2.2770 7.3020 3.4470 CT 2 TRP -0.027500 + 17 HA 2.3960 8.1530 4.1180 H1 2 TRP 0.112300 + 18 CB 3.6470 6.6300 3.4670 CT 2 TRP -0.005000 + 19 HB2 3.6020 5.6820 2.9300 HC 2 TRP 0.033900 + 20 HB3 3.7980 6.5070 4.5390 HC 2 TRP 0.033900 + 21 CG 4.8270 7.4200 3.0000 C* 2 TRP -0.141500 + 22 CD1 5.6790 8.1100 3.7900 CW 2 TRP -0.163800 + 23 HD1 5.7340 8.1640 4.8680 H4 2 TRP 0.206200 + 24 NE1 6.6270 8.7350 3.0040 NA 2 TRP -0.341800 + 25 HE1 7.2550 9.3650 3.4830 H 2 TRP 0.341200 + 26 CE2 6.4650 8.4780 1.6580 CN 2 TRP 0.138000 + 27 CZ2 7.0370 8.8990 0.4520 CA 2 TRP -0.260100 + 28 HZ2 7.8550 9.6030 0.4940 HA 2 TRP 0.157200 + 29 CH2 6.5430 8.4520 -0.7790 CA 2 TRP -0.113400 + 30 HH2 6.9980 8.7870 -1.7000 HA 2 TRP 0.141700 + 31 CZ3 5.4380 7.5920 -0.8070 CA 2 TRP -0.197200 + 32 HZ3 4.9510 7.4260 -1.7570 HA 2 TRP 0.144700 + 33 CE3 4.8900 7.1490 0.4020 CA 2 TRP -0.238700 + 34 HE3 4.0610 6.4560 0.3830 HA 2 TRP 0.170000 + 35 CD2 5.3410 7.6120 1.6480 CB 2 TRP 0.124300 + 36 C 1.8270 7.7200 2.0540 C 2 TRP 0.597300 + 37 O 1.9930 8.8650 1.6380 O 2 TRP -0.567900 + 38 N 1.3040 6.7680 1.2790 N 3 THR -0.415700 + 39 H 1.1020 5.9000 1.7530 H 3 THR 0.271900 + 40 CA 0.6210 7.0580 0.0340 CT 3 THR -0.038900 + 41 HA 1.2370 7.6880 -0.6070 H1 3 THR 0.100700 + 42 CB 0.3030 5.7730 -0.7260 CT 3 THR 0.365400 + 43 HB -0.3910 5.9550 -1.5470 H1 3 THR 0.004300 + 44 CG2 1.5880 5.2390 -1.3520 CT 3 THR -0.243800 + 45 HG21 1.8690 5.6600 -2.3180 HC 3 THR 0.064200 + 46 HG22 2.4010 5.2850 -0.6280 HC 3 THR 0.064200 + 47 HG23 1.4520 4.1640 -1.4680 HC 3 THR 0.064200 + 48 OG1 -0.1560 4.7220 0.0950 OH 3 THR -0.676100 + 49 HG1 -0.6950 4.1610 -0.4670 HO 3 THR 0.410200 + 50 C -0.6710 7.8200 0.2930 C 3 THR 0.597300 + 51 O -1.4410 7.5070 1.1970 O 3 THR -0.567900 + 52 N -0.9550 8.8220 -0.5430 N 4 TRP -0.415700 + 53 H -0.2990 9.0600 -1.2730 H 4 TRP 0.271900 + 54 CA -2.1610 9.6220 -0.4760 CT 4 TRP -0.027500 + 55 HA -2.6090 9.5500 0.5160 H1 4 TRP 0.112300 + 56 CB -1.8300 11.0440 -0.9170 CT 4 TRP -0.005000 + 57 HB2 -2.7620 11.5480 -0.6620 HC 4 TRP 0.033900 + 58 HB3 -1.6460 11.1210 -1.9880 HC 4 TRP 0.033900 + 59 CG -0.6290 11.6400 -0.2550 C* 4 TRP -0.141500 + 60 CD1 0.6030 11.8210 -0.7830 CW 4 TRP -0.163800 + 61 HD1 0.8570 11.6700 -1.8220 H4 4 TRP 0.206200 + 62 NE1 1.4060 12.3980 0.1810 NA 4 TRP -0.341800 + 63 HE1 2.4100 12.4870 0.1060 H 4 TRP 0.341200 + 64 CE2 0.7260 12.7100 1.3400 CN 4 TRP 0.138000 + 65 CZ2 1.0210 13.4160 2.5120 CA 4 TRP -0.260100 + 66 HZ2 1.8990 14.0310 2.6470 HA 4 TRP 0.157200 + 67 CH2 0.0210 13.4800 3.4900 CA 4 TRP -0.113400 + 68 HH2 0.3010 13.9640 4.4140 HA 4 TRP 0.141700 + 69 CZ3 -1.2070 12.8320 3.3140 CA 4 TRP -0.197200 + 70 HZ3 -1.9050 12.9090 4.1350 HA 4 TRP 0.144700 + 71 CE3 -1.5140 12.1430 2.1350 CA 4 TRP -0.238700 + 72 HE3 -2.5390 11.8100 2.2090 HA 4 TRP 0.170000 + 73 CD2 -0.5360 12.0970 1.1280 CB 4 TRP 0.124300 + 74 C -3.1640 8.9010 -1.3650 C 4 TRP 0.597300 + 75 O -4.3440 8.8640 -1.0240 O 4 TRP -0.567900 + 76 N -2.7340 8.4590 -2.5490 N 5 GLU -0.516300 + 77 H -1.8400 8.7280 -2.9340 H 5 GLU 0.293600 + 78 CA -3.4770 7.5610 -3.4100 CT 5 GLU 0.039700 + 79 HA -4.5380 7.8090 -3.3730 H1 5 GLU 0.110500 + 80 CB -3.0310 7.7150 -4.8610 CT 5 GLU 0.056000 + 81 HB2 -2.0330 7.2790 -4.9060 HC 5 GLU -0.017300 + 82 HB3 -2.9580 8.7610 -5.1600 HC 5 GLU -0.017300 + 83 CG -3.8130 6.9800 -5.9460 CT 5 GLU 0.013600 + 84 HG2 -3.9370 5.9440 -5.6330 HC 5 GLU -0.042500 + 85 HG3 -3.1640 6.9730 -6.8220 HC 5 GLU -0.042500 + 86 CD -5.1760 7.5390 -6.3280 C 5 GLU 0.805400 + 87 OE1 -5.8350 6.9500 -7.2120 O2 5 GLU -0.818800 + 88 OE2 -5.6370 8.4950 -5.6680 O2 5 GLU -0.818800 + 89 C -3.2650 6.1730 -2.8230 C 5 GLU 0.536600 + 90 O -2.1640 5.6360 -2.9200 O 5 GLU -0.581900 + 91 N -4.2990 5.5480 -2.2540 N 6 ASN -0.415700 + 92 H -5.2530 5.8760 -2.2840 H 6 ASN 0.271900 + 93 CA -4.3980 4.2440 -1.6310 CT 6 ASN 0.014300 + 94 HA -3.4340 4.1170 -1.1370 H1 6 ASN 0.104800 + 95 CB -5.5950 4.2310 -0.6850 CT 6 ASN -0.204100 + 96 HB2 -6.4620 4.4050 -1.3220 HC 6 ASN 0.079700 + 97 HB3 -5.5610 5.0730 0.0080 HC 6 ASN 0.079700 + 98 CG -5.7270 2.9230 0.0810 C 6 ASN 0.713000 + 99 OD1 -4.7700 2.4140 0.6620 O 6 ASN -0.593100 + 100 ND2 -6.9500 2.3900 0.1360 N 6 ASN -0.919100 + 101 HD21 -7.7410 2.7100 -0.4040 H 6 ASN 0.419600 + 102 HD22 -7.0720 1.6740 0.8370 H 6 ASN 0.419600 + 103 C -4.6560 3.1030 -2.6050 C 6 ASN 0.597300 + 104 O -5.7170 2.9910 -3.2150 O 6 ASN -0.567900 + 105 N -3.6480 2.3420 -3.0370 N 7 GLY -0.415700 + 106 H -2.7730 2.3360 -2.5320 H 7 GLY 0.271900 + 107 CA -3.7530 1.3080 -4.0460 CT 7 GLY -0.025200 + 108 HA2 -3.0210 1.8550 -4.6410 H1 7 GLY 0.069800 + 109 HA3 -4.7150 1.3960 -4.5510 H1 7 GLY 0.069800 + 110 C -3.5480 -0.1110 -3.5360 C 7 GLY 0.597300 + 111 O -3.9190 -0.4810 -2.4240 O 7 GLY -0.567900 + 112 N -2.8390 -0.9590 -4.2840 N 8 LYS -0.347900 + 113 H -2.3800 -0.5510 -5.0860 H 8 LYS 0.274700 + 114 CA -2.6730 -2.3860 -4.0920 CT 8 LYS -0.240000 + 115 HA -3.6090 -2.7290 -3.6530 H1 8 LYS 0.142600 + 116 CB -2.4550 -3.1670 -5.3840 CT 8 LYS -0.009400 + 117 HB2 -3.4080 -3.3420 -5.8830 HC 8 LYS 0.036200 + 118 HB3 -2.1350 -4.1730 -5.1150 HC 8 LYS 0.036200 + 119 CG -1.5030 -2.6190 -6.4440 CT 8 LYS 0.018700 + 120 HG2 -0.5180 -2.7480 -5.9970 HC 8 LYS 0.010300 + 121 HG3 -1.7180 -1.5530 -6.5060 HC 8 LYS 0.010300 + 122 CD -1.5670 -3.1530 -7.8730 CT 8 LYS -0.047900 + 123 HD2 -0.8940 -2.4790 -8.4020 HC 8 LYS 0.062100 + 124 HD3 -2.5880 -3.1150 -8.2550 HC 8 LYS 0.062100 + 125 CE -1.1260 -4.6130 -7.8590 CT 8 LYS -0.014300 + 126 HE2 -1.8090 -5.1880 -7.2340 HP 8 LYS 0.113500 + 127 HE3 -0.0860 -4.6440 -7.5320 HP 8 LYS 0.113500 + 128 NZ -1.1140 -5.0930 -9.2490 N3 8 LYS -0.385400 + 129 HZ1 -0.5390 -4.4820 -9.8120 H 8 LYS 0.340000 + 130 HZ2 -0.6490 -5.9760 -9.4080 H 8 LYS 0.340000 + 131 HZ3 -2.0510 -5.0780 -9.6250 H 8 LYS 0.340000 + 132 C -1.5990 -2.7870 -3.0900 C 8 LYS 0.734100 + 133 O -0.4090 -2.5360 -3.2640 O 8 LYS -0.589400 + 134 N -2.1030 -3.5900 -2.1500 N 9 TRP -0.415700 + 135 H -3.1110 -3.6500 -2.1980 H 9 TRP 0.271900 + 136 CA -1.3750 -4.0590 -0.9890 CT 9 TRP -0.027500 + 137 HA -0.5190 -3.3870 -0.9290 H1 9 TRP 0.112300 + 138 CB -2.2020 -3.8670 0.2790 CT 9 TRP -0.005000 + 139 HB2 -3.1330 -4.4130 0.1290 HC 9 TRP 0.033900 + 140 HB3 -2.4630 -2.8160 0.4090 HC 9 TRP 0.033900 + 141 CG -1.5770 -4.3990 1.5290 C* 9 TRP -0.141500 + 142 CD1 -2.1010 -5.3150 2.3730 CW 9 TRP -0.163800 + 143 HD1 -3.1010 -5.7060 2.2520 H4 9 TRP 0.206200 + 144 NE1 -1.2050 -5.7580 3.3260 NA 9 TRP -0.341800 + 145 HE1 -1.3650 -6.4630 4.0310 H 9 TRP 0.341200 + 146 CE2 -0.0880 -4.9530 3.2240 CN 9 TRP 0.138000 + 147 CZ2 1.0190 -4.8320 4.0730 CA 9 TRP -0.260100 + 148 HZ2 1.1340 -5.5540 4.8680 HA 9 TRP 0.157200 + 149 CH2 2.0180 -3.8800 3.8380 CA 9 TRP -0.113400 + 150 HH2 2.7550 -3.6580 4.5960 HA 9 TRP 0.141700 + 151 CZ3 1.7930 -3.0050 2.7690 CA 9 TRP -0.197200 + 152 HZ3 2.4260 -2.1290 2.7600 HA 9 TRP 0.144700 + 153 CE3 0.6510 -3.0560 1.9600 CA 9 TRP -0.238700 + 154 HE3 0.4150 -2.2160 1.3240 HA 9 TRP 0.170000 + 155 CD2 -0.2610 -4.1150 2.0930 CB 9 TRP 0.124300 + 156 C -0.8290 -5.4750 -1.1010 C 9 TRP 0.597300 + 157 O -1.5450 -6.4710 -1.0260 O 9 TRP -0.567900 + 158 N 0.4980 -5.5990 -1.1850 N 10 THR -0.415700 + 159 H 1.1250 -4.8080 -1.1410 H 10 THR 0.271900 + 160 CA 1.2450 -6.8340 -1.3030 CT 10 THR -0.038900 + 161 HA 0.6660 -7.3380 -2.0770 H1 10 THR 0.100700 + 162 CB 2.6500 -6.6980 -1.8840 CT 10 THR 0.365400 + 163 HB 3.3580 -6.4760 -1.0850 H1 10 THR 0.004300 + 164 CG2 3.1930 -7.9910 -2.4850 CT 10 THR -0.243800 + 165 HG21 3.4000 -7.8050 -3.5390 HC 10 THR 0.064200 + 166 HG22 4.0490 -8.3670 -1.9250 HC 10 THR 0.064200 + 167 HG23 2.4950 -8.8250 -2.4190 HC 10 THR 0.064200 + 168 OG1 2.8800 -5.6690 -2.8200 OH 10 THR -0.676100 + 169 HG1 2.7350 -4.8040 -2.4280 HO 10 THR 0.410200 + 170 C 1.3570 -7.6660 -0.0340 C 10 THR 0.597300 + 171 O 2.2660 -7.4790 0.7710 O 10 THR -0.567900 + 172 N 0.4450 -8.6390 0.0160 N 11 TRP -0.415700 + 173 H -0.3250 -8.6270 -0.6370 H 11 TRP 0.271900 + 174 CA 0.3690 -9.5060 1.1750 CT 11 TRP -0.027500 + 175 HA 0.2920 -8.8770 2.0620 H1 11 TRP 0.112300 + 176 CB -0.9340 -10.2910 1.0520 CT 11 TRP -0.005000 + 177 HB2 -0.8670 -10.9690 0.2010 HC 11 TRP 0.033900 + 178 HB3 -1.6860 -9.5060 0.9740 HC 11 TRP 0.033900 + 179 CG -1.1160 -11.1560 2.2570 C* 11 TRP -0.141500 + 180 CD1 -1.1670 -10.7370 3.5420 CW 11 TRP -0.163800 + 181 HD1 -0.9400 -9.7280 3.8520 H4 11 TRP 0.206200 + 182 NE1 -1.5660 -11.7360 4.4070 NA 11 TRP -0.341800 + 183 HE1 -1.7980 -11.5770 5.3770 H 11 TRP 0.341200 + 184 CE2 -1.8510 -12.9070 3.7360 CN 11 TRP 0.138000 + 185 CZ2 -2.2630 -14.1950 4.0980 CA 11 TRP -0.260100 + 186 HZ2 -2.6470 -14.2750 5.1040 HA 11 TRP 0.157200 + 187 CH2 -2.3900 -15.2080 3.1400 CA 11 TRP -0.113400 + 188 HH2 -3.0040 -16.0650 3.3740 HA 11 TRP 0.141700 + 189 CZ3 -1.9230 -14.9170 1.8530 CA 11 TRP -0.197200 + 190 HZ3 -1.9380 -15.6770 1.0850 HA 11 TRP 0.144700 + 191 CE3 -1.3970 -13.6590 1.5360 CA 11 TRP -0.238700 + 192 HE3 -0.8380 -13.5170 0.6230 HA 11 TRP 0.170000 + 193 CD2 -1.4390 -12.5700 2.4210 CB 11 TRP 0.124300 + 194 C 1.5790 -10.4030 1.3960 C 11 TRP 0.597300 + 195 O 1.7910 -11.2800 0.5620 O 11 TRP -0.567900 + 196 N 2.2520 -10.0440 2.4920 N 12 LYS -0.347900 + 197 H 2.0610 -9.1310 2.8780 H 12 LYS 0.274700 + 198 CA 3.3530 -10.8270 3.0160 CT 12 LYS -0.240000 + 199 HA 4.0220 -11.0650 2.1890 H1 12 LYS 0.142600 + 200 CB 4.1230 -9.8870 3.9380 CT 12 LYS -0.009400 + 201 HB2 4.9620 -10.4580 4.3350 HC 12 LYS 0.036200 + 202 HB3 3.5610 -9.7420 4.8610 HC 12 LYS 0.036200 + 203 CG 4.5190 -8.5310 3.3600 CT 12 LYS 0.018700 + 204 HG2 3.5650 -8.0390 3.1680 HC 12 LYS 0.010300 + 205 HG3 5.0430 -8.5780 2.4060 HC 12 LYS 0.010300 + 206 CD 5.3820 -7.8400 4.4120 CT 12 LYS -0.047900 + 207 HD2 4.9690 -8.0920 5.3890 HC 12 LYS 0.062100 + 208 HD3 5.2410 -6.7660 4.2940 HC 12 LYS 0.062100 + 209 CE 6.8360 -8.2680 4.2400 CT 12 LYS -0.014300 + 210 HE2 7.1330 -7.9280 3.2480 HP 12 LYS 0.113500 + 211 HE3 6.9600 -9.3500 4.1850 HP 12 LYS 0.113500 + 212 NZ 7.6530 -7.7100 5.3290 N3 12 LYS -0.385400 + 213 HZ1 7.8470 -6.7250 5.2140 H 12 LYS 0.340000 + 214 HZ2 7.1980 -7.7880 6.2280 H 12 LYS 0.340000 + 215 HZ3 8.5860 -8.0940 5.2880 H 12 LYS 0.340000 + 216 C 2.9220 -12.0390 3.8290 C 12 LYS 0.734100 + 217 O 3.5830 -13.0670 3.6930 O 12 LYS -0.589400 + 218 N 1.9520 -11.8410 4.7240 N 13 NME -0.415700 + 219 H 1.5230 -10.9340 4.8460 H 13 NME 0.271900 + 220 CH3 1.6920 -12.7810 5.7950 CT 13 NME -0.149000 + 221 HH31 2.6150 -12.8720 6.3670 H1 13 NME 0.097600 + 222 HH32 0.9000 -12.4860 6.4840 H1 13 NME 0.097600 + 223 HH33 1.5530 -13.7860 5.3970 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** diff --git a/test/Test_Cluster_AssignRefs/rep.c4.mol2 b/test/Test_Cluster_AssignRefs/rep.c4.mol2 new file mode 100644 index 0000000000..709e541122 --- /dev/null +++ b/test/Test_Cluster_AssignRefs/rep.c4.mol2 @@ -0,0 +1,476 @@ +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -1.8890 9.1590 7.5690 N3 1 SER 0.184900 + 2 H1 -1.0370 8.6910 7.2960 H 1 SER 0.189800 + 3 H2 -1.9000 9.2980 8.5690 H 1 SER 0.189800 + 4 H3 -2.5380 8.4470 7.2650 H 1 SER 0.189800 + 5 CA -2.0640 10.5010 6.9930 CT 1 SER 0.056700 + 6 HA -3.1000 10.8240 7.1020 HP 1 SER 0.078200 + 7 CB -1.2300 11.5610 7.7070 CT 1 SER 0.259600 + 8 HB2 -1.6700 11.8110 8.6730 H1 1 SER 0.027300 + 9 HB3 -1.2480 12.5030 7.1590 H1 1 SER 0.027300 + 10 OG 0.1230 11.2160 7.9040 OH 1 SER -0.671400 + 11 HG 0.2740 11.7280 8.7010 HO 1 SER 0.423900 + 12 C -1.6130 10.4180 5.5420 C 1 SER 0.616300 + 13 O -2.4980 10.4330 4.6890 O 1 SER -0.572200 + 14 N -0.3660 10.5720 5.0900 N 2 TRP -0.415700 + 15 H 0.3440 10.6120 5.8080 H 2 TRP 0.271900 + 16 CA 0.1950 10.6970 3.7600 CT 2 TRP -0.027500 + 17 HA -0.2180 11.5690 3.2540 H1 2 TRP 0.112300 + 18 CB 1.7100 10.8790 3.7090 CT 2 TRP -0.005000 + 19 HB2 2.2080 9.9860 4.0870 HC 2 TRP 0.033900 + 20 HB3 1.9270 11.6410 4.4580 HC 2 TRP 0.033900 + 21 CG 2.2650 11.2910 2.3840 C* 2 TRP -0.141500 + 22 CD1 2.0320 12.5000 1.8270 CW 2 TRP -0.163800 + 23 HD1 1.5380 13.3330 2.3050 H4 2 TRP 0.206200 + 24 NE1 2.8600 12.5800 0.7240 NA 2 TRP -0.341800 + 25 HE1 2.9290 13.4040 0.1430 H 2 TRP 0.341200 + 26 CE2 3.6620 11.4600 0.6460 CN 2 TRP 0.138000 + 27 CZ2 4.6200 11.1600 -0.3300 CA 2 TRP -0.260100 + 28 HZ2 5.0590 11.8630 -1.0230 HA 2 TRP 0.157200 + 29 CH2 5.0910 9.8430 -0.3770 CA 2 TRP -0.113400 + 30 HH2 5.8540 9.6100 -1.1050 HA 2 TRP 0.141700 + 31 CZ3 4.5450 8.8500 0.4450 CA 2 TRP -0.197200 + 32 HZ3 4.8230 7.8400 0.1820 HA 2 TRP 0.144700 + 33 CE3 3.5490 9.1590 1.3790 CA 2 TRP -0.238700 + 34 HE3 3.1350 8.4300 2.0590 HA 2 TRP 0.170000 + 35 CD2 3.0750 10.4770 1.4830 CB 2 TRP 0.124300 + 36 C -0.1900 9.6090 2.7680 C 2 TRP 0.597300 + 37 O -0.4520 9.9630 1.6210 O 2 TRP -0.567900 + 38 N -0.2680 8.4020 3.3340 N 3 THR -0.415700 + 39 H -0.2600 8.2750 4.3360 H 3 THR 0.271900 + 40 CA -0.6060 7.1720 2.6470 CT 3 THR -0.038900 + 41 HA -0.1800 7.2660 1.6480 H1 3 THR 0.100700 + 42 CB -0.0930 5.9920 3.4680 CT 3 THR 0.365400 + 43 HB -0.5860 5.0810 3.1280 H1 3 THR 0.004300 + 44 CG2 1.3430 5.6480 3.0810 CT 3 THR -0.243800 + 45 HG21 1.3060 5.0050 2.2020 HC 3 THR 0.064200 + 46 HG22 1.9550 6.5430 2.9670 HC 3 THR 0.064200 + 47 HG23 1.8280 5.0680 3.8660 HC 3 THR 0.064200 + 48 OG1 -0.2730 6.2460 4.8430 OH 3 THR -0.676100 + 49 HG1 0.4280 5.7500 5.2710 HO 3 THR 0.410200 + 50 C -2.0730 6.8820 2.3630 C 3 THR 0.597300 + 51 O -2.8840 6.6850 3.2650 O 3 THR -0.567900 + 52 N -2.4140 6.7960 1.0750 N 4 TRP -0.415700 + 53 H -1.6310 6.7560 0.4390 H 4 TRP 0.271900 + 54 CA -3.6890 6.2860 0.6130 CT 4 TRP -0.027500 + 55 HA -4.2880 6.0200 1.4850 H1 4 TRP 0.112300 + 56 CB -4.4650 7.2750 -0.2530 CT 4 TRP -0.005000 + 57 HB2 -5.4500 6.8210 -0.3660 HC 4 TRP 0.033900 + 58 HB3 -4.0220 7.1620 -1.2420 HC 4 TRP 0.033900 + 59 CG -4.6320 8.7230 0.0770 C* 4 TRP -0.141500 + 60 CD1 -3.9020 9.7130 -0.4830 CW 4 TRP -0.163800 + 61 HD1 -3.0890 9.5530 -1.1760 H4 4 TRP 0.206200 + 62 NE1 -4.4730 10.9230 -0.1410 NA 4 TRP -0.341800 + 63 HE1 -4.1360 11.8610 -0.3060 H 4 TRP 0.341200 + 64 CE2 -5.4690 10.7460 0.7980 CN 4 TRP 0.138000 + 65 CZ2 -6.3300 11.6930 1.3650 CA 4 TRP -0.260100 + 66 HZ2 -6.2760 12.7460 1.1300 HA 4 TRP 0.157200 + 67 CH2 -7.3740 11.1960 2.1540 CA 4 TRP -0.113400 + 68 HH2 -8.2300 11.8220 2.3620 HA 4 TRP 0.141700 + 69 CZ3 -7.6300 9.8240 2.2590 CA 4 TRP -0.197200 + 70 HZ3 -8.3790 9.4820 2.9590 HA 4 TRP 0.144700 + 71 CE3 -6.7760 8.9050 1.6380 CA 4 TRP -0.238700 + 72 HE3 -6.9740 7.8720 1.8840 HA 4 TRP 0.170000 + 73 CD2 -5.7030 9.3470 0.8480 CB 4 TRP 0.124300 + 74 C -3.6320 4.9260 -0.0680 C 4 TRP 0.597300 + 75 O -4.2790 3.9520 0.3090 O 4 TRP -0.567900 + 76 N -2.7950 4.8720 -1.1060 N 5 GLU -0.516300 + 77 H -2.2780 5.7080 -1.3390 H 5 GLU 0.293600 + 78 CA -2.5350 3.7230 -1.9500 CT 5 GLU 0.039700 + 79 HA -3.0070 2.9480 -1.3460 H1 5 GLU 0.110500 + 80 CB -3.4130 3.5240 -3.1830 CT 5 GLU 0.056000 + 81 HB2 -3.1390 4.1410 -4.0380 HC 5 GLU -0.017300 + 82 HB3 -4.3860 3.7870 -2.7670 HC 5 GLU -0.017300 + 83 CG -3.4700 2.1080 -3.7480 CT 5 GLU 0.013600 + 84 HG2 -2.4470 1.7930 -3.9530 HC 5 GLU -0.042500 + 85 HG3 -4.0390 2.4250 -4.6230 HC 5 GLU -0.042500 + 86 CD -4.1890 1.1230 -2.8370 C 5 GLU 0.805400 + 87 OE1 -3.8030 0.7710 -1.7020 O2 5 GLU -0.818800 + 88 OE2 -5.2630 0.6010 -3.2070 O2 5 GLU -0.818800 + 89 C -1.0580 3.5180 -2.2550 C 5 GLU 0.536600 + 90 O -0.3010 4.4140 -2.6190 O 5 GLU -0.581900 + 91 N -0.6680 2.2650 -2.0090 N 6 ASN -0.415700 + 92 H -1.3230 1.6560 -1.5390 H 6 ASN 0.271900 + 93 CA 0.6390 1.6960 -2.2670 CT 6 ASN 0.014300 + 94 HA 1.2390 2.4530 -2.7720 H1 6 ASN 0.104800 + 95 CB 1.4120 1.3660 -0.9930 CT 6 ASN -0.204100 + 96 HB2 2.2240 0.7030 -1.2910 HC 6 ASN 0.079700 + 97 HB3 0.7120 0.8820 -0.3110 HC 6 ASN 0.079700 + 98 CG 2.1540 2.5500 -0.3910 C 6 ASN 0.713000 + 99 OD1 2.8090 3.3470 -1.0580 O 6 ASN -0.593100 + 100 ND2 2.3590 2.5190 0.9280 N 6 ASN -0.919100 + 101 HD21 1.8690 1.8970 1.5560 H 6 ASN 0.419600 + 102 HD22 3.0240 3.1960 1.2720 H 6 ASN 0.419600 + 103 C 0.5090 0.4880 -3.1850 C 6 ASN 0.597300 + 104 O -0.4570 -0.2500 -3.0040 O 6 ASN -0.567900 + 105 N 1.4630 0.2470 -4.0870 N 7 GLY -0.415700 + 106 H 2.3720 0.6580 -3.9320 H 7 GLY 0.271900 + 107 CA 1.3990 -0.9020 -4.9670 CT 7 GLY -0.025200 + 108 HA2 2.1800 -0.8820 -5.7280 H1 7 GLY 0.069800 + 109 HA3 0.5010 -0.7990 -5.5760 H1 7 GLY 0.069800 + 110 C 1.4480 -2.2750 -4.3130 C 7 GLY 0.597300 + 111 O 0.7270 -2.5760 -3.3640 O 7 GLY -0.567900 + 112 N 2.3610 -3.1180 -4.8010 N 8 LYS -0.347900 + 113 H 3.0800 -2.7840 -5.4260 H 8 LYS 0.274700 + 114 CA 2.5410 -4.5140 -4.4580 CT 8 LYS -0.240000 + 115 HA 1.6270 -5.0150 -4.1380 H1 8 LYS 0.142600 + 116 CB 3.1230 -5.2830 -5.6410 CT 8 LYS -0.009400 + 117 HB2 2.4350 -5.2430 -6.4860 HC 8 LYS 0.036200 + 118 HB3 3.3350 -6.3180 -5.3720 HC 8 LYS 0.036200 + 119 CG 4.4160 -4.7460 -6.2480 CT 8 LYS 0.018700 + 120 HG2 5.3080 -4.9600 -5.6600 HC 8 LYS 0.010300 + 121 HG3 4.3930 -3.6740 -6.4390 HC 8 LYS 0.010300 + 122 CD 4.7260 -5.5030 -7.5360 CT 8 LYS -0.047900 + 123 HD2 3.9920 -5.2720 -8.3080 HC 8 LYS 0.062100 + 124 HD3 4.5840 -6.5430 -7.2410 HC 8 LYS 0.062100 + 125 CE 6.1480 -5.3380 -8.0660 CT 8 LYS -0.014300 + 126 HE2 6.5210 -6.2900 -8.4440 HP 8 LYS 0.113500 + 127 HE3 6.8480 -5.0250 -7.2900 HP 8 LYS 0.113500 + 128 NZ 6.1770 -4.4200 -9.2140 N3 8 LYS -0.385400 + 129 HZ1 6.0460 -3.5470 -8.7220 H 8 LYS 0.340000 + 130 HZ2 7.1310 -4.3920 -9.5460 H 8 LYS 0.340000 + 131 HZ3 5.4710 -4.5500 -9.9250 H 8 LYS 0.340000 + 132 C 3.5120 -4.5190 -3.2860 C 8 LYS 0.734100 + 133 O 4.6240 -5.0420 -3.2860 O 8 LYS -0.589400 + 134 N 2.9250 -4.2560 -2.1160 N 9 TRP -0.415700 + 135 H 2.0100 -3.8790 -2.3160 H 9 TRP 0.271900 + 136 CA 3.3410 -4.2620 -0.7280 CT 9 TRP -0.027500 + 137 HA 4.4100 -4.0450 -0.7240 H1 9 TRP 0.112300 + 138 CB 2.6250 -3.0680 -0.1040 CT 9 TRP -0.005000 + 139 HB2 1.5890 -3.2940 0.1480 HC 9 TRP 0.033900 + 140 HB3 2.8350 -2.1940 -0.7210 HC 9 TRP 0.033900 + 141 CG 3.2880 -2.4620 1.0910 C* 9 TRP -0.141500 + 142 CD1 2.9250 -2.4360 2.3930 CW 9 TRP -0.163800 + 143 HD1 1.9490 -2.7990 2.6780 H4 9 TRP 0.206200 + 144 NE1 3.8550 -1.8450 3.2240 NA 9 TRP -0.341800 + 145 HE1 3.8850 -1.8480 4.2340 H 9 TRP 0.341200 + 146 CE2 4.8270 -1.3030 2.4080 CN 9 TRP 0.138000 + 147 CZ2 5.9110 -0.4710 2.7140 CA 9 TRP -0.260100 + 148 HZ2 6.1390 -0.1560 3.7210 HA 9 TRP 0.157200 + 149 CH2 6.8410 -0.1410 1.7220 CA 9 TRP -0.113400 + 150 HH2 7.7250 0.4050 2.0180 HA 9 TRP 0.141700 + 151 CZ3 6.5840 -0.5900 0.4210 CA 9 TRP -0.197200 + 152 HZ3 7.2310 -0.2350 -0.3680 HA 9 TRP 0.144700 + 153 CE3 5.4240 -1.2970 0.0820 CA 9 TRP -0.238700 + 154 HE3 5.1390 -1.4650 -0.9460 HA 9 TRP 0.170000 + 155 CD2 4.4790 -1.6200 1.0690 CB 9 TRP 0.124300 + 156 C 2.9450 -5.5930 -0.1050 C 9 TRP 0.597300 + 157 O 3.0220 -6.6750 -0.6820 O 9 TRP -0.567900 + 158 N 2.5310 -5.6090 1.1640 N 10 THR -0.415700 + 159 H 2.7110 -4.7940 1.7310 H 10 THR 0.271900 + 160 CA 2.2540 -6.8740 1.8150 CT 10 THR -0.038900 + 161 HA 2.9820 -7.6670 1.6440 H1 10 THR 0.100700 + 162 CB 2.2070 -6.6220 3.3200 CT 10 THR 0.365400 + 163 HB 1.7220 -5.6670 3.5260 H1 10 THR 0.004300 + 164 CG2 1.4560 -7.6590 4.1490 CT 10 THR -0.243800 + 165 HG21 1.5810 -7.4640 5.2140 HC 10 THR 0.064200 + 166 HG22 0.4020 -7.4680 3.9460 HC 10 THR 0.064200 + 167 HG23 1.7250 -8.6400 3.7550 HC 10 THR 0.064200 + 168 OG1 3.4600 -6.5010 3.9540 OH 10 THR -0.676100 + 169 HG1 3.3850 -6.0970 4.8220 HO 10 THR 0.410200 + 170 C 0.8890 -7.3540 1.3440 C 10 THR 0.597300 + 171 O -0.1720 -6.7600 1.5240 O 10 THR -0.567900 + 172 N 0.9060 -8.5220 0.6990 N 11 TRP -0.415700 + 173 H 1.7230 -9.1150 0.7340 H 11 TRP 0.271900 + 174 CA -0.1880 -9.0660 -0.0800 CT 11 TRP -0.027500 + 175 HA -0.7370 -8.2200 -0.4950 H1 11 TRP 0.112300 + 176 CB 0.4120 -10.0100 -1.1170 CT 11 TRP -0.005000 + 177 HB2 1.1130 -10.7100 -0.6610 HC 11 TRP 0.033900 + 178 HB3 0.8870 -9.3680 -1.8590 HC 11 TRP 0.033900 + 179 CG -0.5390 -10.9280 -1.8160 C* 11 TRP -0.141500 + 180 CD1 -1.3130 -10.6860 -2.8980 CW 11 TRP -0.163800 + 181 HD1 -1.3370 -9.7640 -3.4600 H4 11 TRP 0.206200 + 182 NE1 -1.9710 -11.7860 -3.4110 NA 11 TRP -0.341800 + 183 HE1 -2.3840 -11.8640 -4.3300 H 11 TRP 0.341200 + 184 CE2 -1.9570 -12.7630 -2.4370 CN 11 TRP 0.138000 + 185 CZ2 -2.7850 -13.8650 -2.1910 CA 11 TRP -0.260100 + 186 HZ2 -3.6310 -14.0120 -2.8460 HA 11 TRP 0.157200 + 187 CH2 -2.6000 -14.7090 -1.0890 CA 11 TRP -0.113400 + 188 HH2 -3.3150 -15.4730 -0.8230 HA 11 TRP 0.141700 + 189 CZ3 -1.5180 -14.3450 -0.2780 CA 11 TRP -0.197200 + 190 HZ3 -1.3250 -14.9360 0.6040 HA 11 TRP 0.144700 + 191 CE3 -0.8090 -13.1460 -0.4190 CA 11 TRP -0.238700 + 192 HE3 -0.0380 -12.8340 0.2700 HA 11 TRP 0.170000 + 193 CD2 -1.0340 -12.2590 -1.4840 CB 11 TRP 0.124300 + 194 C -1.0790 -9.7520 0.9460 C 11 TRP 0.597300 + 195 O -0.7100 -10.6730 1.6720 O 11 TRP -0.567900 + 196 N -2.3440 -9.3260 0.9490 N 12 LYS -0.347900 + 197 H -2.4560 -8.3390 0.7700 H 12 LYS 0.274700 + 198 CA -3.4700 -9.9260 1.6360 CT 12 LYS -0.240000 + 199 HA -3.0970 -10.4390 2.5220 H1 12 LYS 0.142600 + 200 CB -4.3840 -8.8140 2.1420 CT 12 LYS -0.009400 + 201 HB2 -5.3890 -9.1120 2.4400 HC 12 LYS 0.036200 + 202 HB3 -4.4390 -8.0090 1.4090 HC 12 LYS 0.036200 + 203 CG -3.7990 -8.0920 3.3520 CT 12 LYS 0.018700 + 204 HG2 -2.8890 -7.5660 3.0640 HC 12 LYS 0.010300 + 205 HG3 -3.6910 -8.7240 4.2330 HC 12 LYS 0.010300 + 206 CD -4.8480 -7.0240 3.6500 CT 12 LYS -0.047900 + 207 HD2 -5.6910 -7.4110 4.2220 HC 12 LYS 0.062100 + 208 HD3 -5.1300 -6.4950 2.7400 HC 12 LYS 0.062100 + 209 CE -4.1080 -6.0190 4.5290 CT 12 LYS -0.014300 + 210 HE2 -3.1830 -5.6350 4.0990 HP 12 LYS 0.113500 + 211 HE3 -3.8850 -6.5530 5.4520 HP 12 LYS 0.113500 + 212 NZ -4.8770 -4.8020 4.8290 N3 12 LYS -0.385400 + 213 HZ1 -5.1320 -4.3050 3.9870 H 12 LYS 0.340000 + 214 HZ2 -5.7180 -4.9680 5.3620 H 12 LYS 0.340000 + 215 HZ3 -4.2500 -4.2630 5.4100 H 12 LYS 0.340000 + 216 C -4.3950 -10.7780 0.7790 C 12 LYS 0.734100 + 217 O -4.4830 -11.9390 1.1720 O 12 LYS -0.589400 + 218 N -4.8320 -10.2020 -0.3440 N 13 NME -0.415700 + 219 H -4.6470 -9.2390 -0.5870 H 13 NME 0.271900 + 220 CH3 -5.7200 -10.8660 -1.2770 CT 13 NME -0.149000 + 221 HH31 -5.5910 -11.9460 -1.3400 H1 13 NME 0.097600 + 222 HH32 -6.7570 -10.8860 -0.9420 H1 13 NME 0.097600 + 223 HH33 -5.7770 -10.3580 -2.2400 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** diff --git a/test/Test_Cluster_Cache/RunTest.sh b/test/Test_Cluster_Cache/RunTest.sh new file mode 100755 index 0000000000..f8e8f05de3 --- /dev/null +++ b/test/Test_Cluster_Cache/RunTest.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +. ../MasterTest.sh + +CleanFiles cluster.in *.cnumvtime.dat *.info.dat *.summary.dat PW0 PW1 \ + CpptrajPairwiseCache + +INPUT="-i cluster.in" +TESTNAME='Cluster pairwise cache tests' +Requires netcdf + +# +Cluster() { + PREFIX=$1 + if [ "$PREFIX" = 'random' ] ; then + RNG='rng setdefault marsaglia' + else + RNG='' + fi + SIEVEARG=$2 + SAVEARG=$3 + cat > cluster.in < cluster.in < dbscan.in < dbscan.in < dbscan.in < dbscan.in < dbscan.in < ds.in < ds.in < ds.in < dpeaks.in < kmeans.in < kmeans.in < kmeans.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in < cluster.in <MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -5.8550 10.4160 2.3490 N3 1 SER 0.184900 + 2 H1 -5.6670 9.5970 1.7870 H 1 SER 0.189800 + 3 H2 -6.8050 10.3940 2.6890 H 1 SER 0.189800 + 4 H3 -5.6390 11.2490 1.8200 H 1 SER 0.189800 + 5 CA -4.9110 10.3950 3.4770 CT 1 SER 0.056700 + 6 HA -5.3400 10.8830 4.3530 HP 1 SER 0.078200 + 7 CB -4.5290 8.9600 3.8260 CT 1 SER 0.259600 + 8 HB2 -5.3880 8.3850 4.1730 H1 1 SER 0.027300 + 9 HB3 -3.8220 8.8960 4.6540 H1 1 SER 0.027300 + 10 OG -4.0540 8.3980 2.6230 OH 1 SER -0.671400 + 11 HG -4.0440 7.4490 2.7670 HO 1 SER 0.423900 + 12 C -3.6850 11.2230 3.1190 C 1 SER 0.616300 + 13 O -3.5790 11.8150 2.0470 O 1 SER -0.572200 + 14 N -2.7260 11.3310 4.0420 N 2 TRP -0.415700 + 15 H -2.8950 10.7610 4.8580 H 2 TRP 0.271900 + 16 CA -1.3860 11.8790 3.9820 CT 2 TRP -0.027500 + 17 HA -1.4900 12.9050 3.6290 H1 2 TRP 0.112300 + 18 CB -0.6290 11.9190 5.3070 CT 2 TRP -0.005000 + 19 HB2 -0.4390 10.9260 5.7120 HC 2 TRP 0.033900 + 20 HB3 -1.3560 12.3050 6.0220 HC 2 TRP 0.033900 + 21 CG 0.7010 12.5990 5.3710 C* 2 TRP -0.141500 + 22 CD1 0.9780 13.9060 5.5800 CW 2 TRP -0.163800 + 23 HD1 0.2900 14.7300 5.6930 H4 2 TRP 0.206200 + 24 NE1 2.3440 14.1060 5.5950 NA 2 TRP -0.341800 + 25 HE1 2.8680 14.9660 5.6730 H 2 TRP 0.341200 + 26 CE2 3.0420 12.9340 5.3860 CN 2 TRP 0.138000 + 27 CZ2 4.3840 12.5740 5.5580 CA 2 TRP -0.260100 + 28 HZ2 5.0490 13.3560 5.8930 HA 2 TRP 0.157200 + 29 CH2 4.7660 11.2330 5.4340 CA 2 TRP -0.113400 + 30 HH2 5.7860 10.9470 5.6430 HA 2 TRP 0.141700 + 31 CZ3 3.8070 10.2490 5.1640 CA 2 TRP -0.197200 + 32 HZ3 4.1920 9.2440 5.2600 HA 2 TRP 0.144700 + 33 CE3 2.4630 10.6350 5.2200 CA 2 TRP -0.238700 + 34 HE3 1.7550 9.8210 5.1560 HA 2 TRP 0.170000 + 35 CD2 2.0120 11.9620 5.2980 CB 2 TRP 0.124300 + 36 C -0.5630 11.3400 2.8200 C 2 TRP 0.597300 + 37 O 0.1660 12.0810 2.1640 O 2 TRP -0.567900 + 38 N -0.6330 10.0240 2.6080 N 3 THR -0.415700 + 39 H -1.2400 9.4970 3.2200 H 3 THR 0.271900 + 40 CA -0.2040 9.2440 1.4650 CT 3 THR -0.038900 + 41 HA 0.7940 9.6510 1.3040 H1 3 THR 0.100700 + 42 CB 0.1810 7.8160 1.8410 CT 3 THR 0.365400 + 43 HB 0.1640 7.1350 0.9900 H1 3 THR 0.004300 + 44 CG2 1.5210 7.6320 2.5470 CT 3 THR -0.243800 + 45 HG21 1.6320 8.4380 3.2720 HC 3 THR 0.064200 + 46 HG22 1.5990 6.6260 2.9590 HC 3 THR 0.064200 + 47 HG23 2.2100 7.6610 1.7030 HC 3 THR 0.064200 + 48 OG1 -0.6540 7.3360 2.8710 OH 3 THR -0.676100 + 49 HG1 -1.4990 7.0320 2.5310 HO 3 THR 0.410200 + 50 C -1.0150 9.2550 0.1770 C 3 THR 0.597300 + 51 O -2.0140 8.5490 0.0590 O 3 THR -0.567900 + 52 N -0.5760 10.0870 -0.7700 N 4 TRP -0.415700 + 53 H 0.2860 10.5770 -0.5760 H 4 TRP 0.271900 + 54 CA -1.2210 10.2690 -2.0550 CT 4 TRP -0.027500 + 55 HA -2.2390 10.6370 -1.9300 H1 4 TRP 0.112300 + 56 CB -0.4470 11.2630 -2.9160 CT 4 TRP -0.005000 + 57 HB2 -0.8210 11.2170 -3.9380 HC 4 TRP 0.033900 + 58 HB3 0.6050 11.0020 -3.0210 HC 4 TRP 0.033900 + 59 CG -0.3740 12.6530 -2.3690 C* 4 TRP -0.141500 + 60 CD1 0.6610 13.1490 -1.6540 CW 4 TRP -0.163800 + 61 HD1 1.6290 12.6890 -1.5200 H4 4 TRP 0.206200 + 62 NE1 0.3900 14.4060 -1.1520 NA 4 TRP -0.341800 + 63 HE1 1.0410 14.8000 -0.4880 H 4 TRP 0.341200 + 64 CE2 -0.9560 14.6580 -1.3220 CN 4 TRP 0.138000 + 65 CZ2 -1.7940 15.7250 -0.9740 CA 4 TRP -0.260100 + 66 HZ2 -1.3810 16.4780 -0.3200 HA 4 TRP 0.157200 + 67 CH2 -3.1400 15.6770 -1.3560 CA 4 TRP -0.113400 + 68 HH2 -3.7130 16.5590 -1.1140 HA 4 TRP 0.141700 + 69 CZ3 -3.7120 14.5290 -1.9190 CA 4 TRP -0.197200 + 70 HZ3 -4.7790 14.4260 -2.0490 HA 4 TRP 0.144700 + 71 CE3 -2.8360 13.5110 -2.3140 CA 4 TRP -0.238700 + 72 HE3 -3.1130 12.5970 -2.8180 HA 4 TRP 0.170000 + 73 CD2 -1.4450 13.6210 -2.1580 CB 4 TRP 0.124300 + 74 C -1.3400 8.9980 -2.8840 C 4 TRP 0.597300 + 75 O -2.4310 8.4760 -3.1020 O 4 TRP -0.567900 + 76 N -0.2480 8.3120 -3.2300 N 5 GLU -0.516300 + 77 H 0.6230 8.6860 -2.8790 H 5 GLU 0.293600 + 78 CA -0.1410 6.9840 -3.8000 CT 5 GLU 0.039700 + 79 HA -0.8840 6.8170 -4.5800 H1 5 GLU 0.110500 + 80 CB 1.1410 6.9920 -4.6280 CT 5 GLU 0.056000 + 81 HB2 1.9410 7.3510 -3.9800 HC 5 GLU -0.017300 + 82 HB3 1.0790 7.8060 -5.3490 HC 5 GLU -0.017300 + 83 CG 1.5920 5.6830 -5.2700 CT 5 GLU 0.013600 + 84 HG2 1.8610 4.9040 -4.5580 HC 5 GLU -0.042500 + 85 HG3 2.4700 5.9330 -5.8660 HC 5 GLU -0.042500 + 86 CD 0.5990 5.2520 -6.3400 C 5 GLU 0.805400 + 87 OE1 0.6940 5.8150 -7.4520 O2 5 GLU -0.818800 + 88 OE2 -0.3430 4.4880 -6.0380 O2 5 GLU -0.818800 + 89 C -0.1530 5.9410 -2.6920 C 5 GLU 0.536600 + 90 O 0.2960 6.2940 -1.6040 O 5 GLU -0.581900 + 91 N -0.9350 4.8860 -2.9330 N 6 ASN -0.415700 + 92 H -1.1850 4.6960 -3.8930 H 6 ASN 0.271900 + 93 CA -1.4090 3.9650 -1.9190 CT 6 ASN 0.014300 + 94 HA -1.0860 4.3890 -0.9680 H1 6 ASN 0.104800 + 95 CB -2.9310 3.8520 -1.9270 CT 6 ASN -0.204100 + 96 HB2 -3.2640 3.3570 -2.8390 HC 6 ASN 0.079700 + 97 HB3 -3.3870 4.8420 -1.8870 HC 6 ASN 0.079700 + 98 CG -3.4250 3.0170 -0.7550 C 6 ASN 0.713000 + 99 OD1 -4.2120 2.0760 -0.8290 O 6 ASN -0.593100 + 100 ND2 -3.0290 3.2960 0.4890 N 6 ASN -0.919100 + 101 HD21 -2.2540 3.9400 0.5530 H 6 ASN 0.419600 + 102 HD22 -3.3550 2.8230 1.3190 H 6 ASN 0.419600 + 103 C -0.7950 2.5930 -2.1590 C 6 ASN 0.597300 + 104 O -0.9230 1.9530 -3.2000 O 6 ASN -0.567900 + 105 N 0.0300 2.1420 -1.2120 N 7 GLY -0.415700 + 106 H 0.2020 2.7420 -0.4180 H 7 GLY 0.271900 + 107 CA 0.6640 0.8400 -1.1740 CT 7 GLY -0.025200 + 108 HA2 1.7350 0.9910 -1.0400 H1 7 GLY 0.069800 + 109 HA3 0.5630 0.3560 -2.1450 H1 7 GLY 0.069800 + 110 C 0.0180 -0.0730 -0.1410 C 7 GLY 0.597300 + 111 O 0.2150 0.1300 1.0550 O 7 GLY -0.567900 + 112 N -0.7260 -1.0590 -0.6470 N 8 LYS -0.347900 + 113 H -0.9550 -0.9960 -1.6290 H 8 LYS 0.274700 + 114 CA -1.2790 -2.1170 0.1740 CT 8 LYS -0.240000 + 115 HA -1.3510 -1.7400 1.1940 H1 8 LYS 0.142600 + 116 CB -2.7160 -2.5240 -0.1390 CT 8 LYS -0.009400 + 117 HB2 -3.4260 -1.7000 -0.0640 HC 8 LYS 0.036200 + 118 HB3 -3.1770 -3.2670 0.5120 HC 8 LYS 0.036200 + 119 CG -2.8110 -3.2190 -1.4950 CT 8 LYS 0.018700 + 120 HG2 -2.3430 -4.2010 -1.4250 HC 8 LYS 0.010300 + 121 HG3 -2.3500 -2.6320 -2.2890 HC 8 LYS 0.010300 + 122 CD -4.2490 -3.5050 -1.9160 CT 8 LYS -0.047900 + 123 HD2 -4.2550 -3.9250 -2.9220 HC 8 LYS 0.062100 + 124 HD3 -4.7050 -2.5150 -1.9440 HC 8 LYS 0.062100 + 125 CE -4.9150 -4.4420 -0.9130 CT 8 LYS -0.014300 + 126 HE2 -4.9110 -4.0040 0.0850 HP 8 LYS 0.113500 + 127 HE3 -4.3060 -5.3420 -0.8320 HP 8 LYS 0.113500 + 128 NZ -6.2870 -4.7500 -1.3460 N3 8 LYS -0.385400 + 129 HZ1 -6.7340 -5.3900 -0.7040 H 8 LYS 0.340000 + 130 HZ2 -6.9170 -3.9900 -1.1330 H 8 LYS 0.340000 + 131 HZ3 -6.4140 -5.1360 -2.2700 H 8 LYS 0.340000 + 132 C -0.2990 -3.2770 0.0780 C 8 LYS 0.734100 + 133 O 0.0740 -3.5890 -1.0510 O 8 LYS -0.589400 + 134 N 0.1350 -3.8990 1.1770 N 9 TRP -0.415700 + 135 H -0.1440 -3.5300 2.0750 H 9 TRP 0.271900 + 136 CA 0.8910 -5.1310 1.0840 CT 9 TRP -0.027500 + 137 HA 1.7030 -5.0840 0.3580 H1 9 TRP 0.112300 + 138 CB 1.4390 -5.4680 2.4680 CT 9 TRP -0.005000 + 139 HB2 0.5840 -5.5400 3.1410 HC 9 TRP 0.033900 + 140 HB3 2.1000 -4.6260 2.6740 HC 9 TRP 0.033900 + 141 CG 2.2540 -6.7110 2.6260 C* 9 TRP -0.141500 + 142 CD1 2.1160 -7.6400 3.5980 CW 9 TRP -0.163800 + 143 HD1 1.4480 -7.5260 4.4390 H4 9 TRP 0.206200 + 144 NE1 2.9870 -8.6950 3.4080 NA 9 TRP -0.341800 + 145 HE1 2.7720 -9.5990 3.8040 H 9 TRP 0.341200 + 146 CE2 3.8010 -8.5070 2.3090 CN 9 TRP 0.138000 + 147 CZ2 4.8870 -9.2370 1.8130 CA 9 TRP -0.260100 + 148 HZ2 5.2120 -10.2050 2.1640 HA 9 TRP 0.157200 + 149 CH2 5.4410 -8.7790 0.6110 CA 9 TRP -0.113400 + 150 HH2 6.2150 -9.3730 0.1490 HA 9 TRP 0.141700 + 151 CZ3 4.9080 -7.6590 -0.0370 CA 9 TRP -0.197200 + 152 HZ3 5.3870 -7.2280 -0.9040 HA 9 TRP 0.144700 + 153 CE3 3.8960 -6.9080 0.5730 CA 9 TRP -0.238700 + 154 HE3 3.6080 -5.9660 0.1310 HA 9 TRP 0.170000 + 155 CD2 3.3020 -7.2850 1.7890 CB 9 TRP 0.124300 + 156 C 0.0550 -6.3360 0.6780 C 9 TRP 0.597300 + 157 O -0.9570 -6.6340 1.3100 O 9 TRP -0.567900 + 158 N 0.4840 -6.9360 -0.4350 N 10 THR -0.415700 + 159 H 1.3890 -6.6770 -0.7990 H 10 THR 0.271900 + 160 CA -0.2150 -8.0460 -1.0500 CT 10 THR -0.038900 + 161 HA -1.2790 -7.9320 -0.8450 H1 10 THR 0.100700 + 162 CB 0.1530 -8.2370 -2.5180 CT 10 THR 0.365400 + 163 HB 1.2280 -8.1680 -2.6830 H1 10 THR 0.004300 + 164 CG2 -0.2700 -9.5870 -3.0900 CT 10 THR -0.243800 + 165 HG21 -1.3530 -9.6920 -3.0270 HC 10 THR 0.064200 + 166 HG22 -0.2070 -9.5860 -4.1780 HC 10 THR 0.064200 + 167 HG23 0.3170 -10.3900 -2.6440 HC 10 THR 0.064200 + 168 OG1 -0.5950 -7.3090 -3.2710 OH 10 THR -0.676100 + 169 HG1 -0.3000 -6.4100 -3.1090 HO 10 THR 0.410200 + 170 C 0.2220 -9.3120 -0.3260 C 10 THR 0.597300 + 171 O 1.3820 -9.7090 -0.4240 O 10 THR -0.567900 + 172 N -0.6780 -10.1060 0.2570 N 11 TRP -0.415700 + 173 H -1.6440 -9.8110 0.2870 H 11 TRP 0.271900 + 174 CA -0.3260 -11.3320 0.9440 CT 11 TRP -0.027500 + 175 HA 0.7110 -11.2360 1.2660 H1 11 TRP 0.112300 + 176 CB -1.2620 -11.4000 2.1470 CT 11 TRP -0.005000 + 177 HB2 -2.2320 -11.6840 1.7380 HC 11 TRP 0.033900 + 178 HB3 -1.3640 -10.4210 2.6160 HC 11 TRP 0.033900 + 179 CG -0.8640 -12.3300 3.2480 C* 11 TRP -0.141500 + 180 CD1 -0.0800 -11.9140 4.2680 CW 11 TRP -0.163800 + 181 HD1 0.2580 -10.9040 4.4460 H4 11 TRP 0.206200 + 182 NE1 0.4260 -12.9920 4.9670 NA 11 TRP -0.341800 + 183 HE1 1.1530 -12.9530 5.6670 H 11 TRP 0.341200 + 184 CE2 -0.1510 -14.1550 4.5010 CN 11 TRP 0.138000 + 185 CZ2 -0.1600 -15.4410 5.0550 CA 11 TRP -0.260100 + 186 HZ2 0.2370 -15.5890 6.0490 HA 11 TRP 0.157200 + 187 CH2 -0.9010 -16.4100 4.3680 CA 11 TRP -0.113400 + 188 HH2 -0.9980 -17.4100 4.7640 HA 11 TRP 0.141700 + 189 CZ3 -1.6640 -16.1410 3.2260 CA 11 TRP -0.197200 + 190 HZ3 -2.1510 -17.0030 2.7950 HA 11 TRP 0.144700 + 191 CE3 -1.6870 -14.8120 2.7860 CA 11 TRP -0.238700 + 192 HE3 -2.2190 -14.5490 1.8840 HA 11 TRP 0.170000 + 193 CD2 -1.0050 -13.7700 3.4350 CB 11 TRP 0.124300 + 194 C -0.4380 -12.5040 -0.0200 C 11 TRP 0.597300 + 195 O -1.4760 -12.8650 -0.5710 O 11 TRP -0.567900 + 196 N 0.7740 -12.9940 -0.2920 N 12 LYS -0.347900 + 197 H 1.5450 -12.5360 0.1720 H 12 LYS 0.274700 + 198 CA 0.9700 -13.7710 -1.4990 CT 12 LYS -0.240000 + 199 HA 0.5180 -13.3010 -2.3720 H1 12 LYS 0.142600 + 200 CB 2.4820 -13.8520 -1.6930 CT 12 LYS -0.009400 + 201 HB2 2.7580 -14.5560 -2.4780 HC 12 LYS 0.036200 + 202 HB3 2.9080 -14.3690 -0.8330 HC 12 LYS 0.036200 + 203 CG 3.1830 -12.5000 -1.7790 CT 12 LYS 0.018700 + 204 HG2 3.4340 -12.1260 -0.7870 HC 12 LYS 0.010300 + 205 HG3 2.5880 -11.7260 -2.2650 HC 12 LYS 0.010300 + 206 CD 4.5290 -12.6390 -2.4830 CT 12 LYS -0.047900 + 207 HD2 4.3850 -13.0990 -3.4610 HC 12 LYS 0.062100 + 208 HD3 5.1330 -13.3360 -1.9010 HC 12 LYS 0.062100 + 209 CE 5.1660 -11.2620 -2.6470 CT 12 LYS -0.014300 + 210 HE2 5.1610 -10.7260 -1.6980 HP 12 LYS 0.113500 + 211 HE3 4.5500 -10.6620 -3.3160 HP 12 LYS 0.113500 + 212 NZ 6.5010 -11.1720 -3.2600 N3 12 LYS -0.385400 + 213 HZ1 6.3360 -11.5900 -4.1640 H 12 LYS 0.340000 + 214 HZ2 6.8700 -10.2350 -3.3320 H 12 LYS 0.340000 + 215 HZ3 7.1660 -11.6480 -2.6670 H 12 LYS 0.340000 + 216 C 0.4970 -15.1920 -1.2260 C 12 LYS 0.734100 + 217 O -0.2390 -15.7400 -2.0440 O 12 LYS -0.589400 + 218 N 0.9570 -15.7500 -0.1040 N 13 NME -0.415700 + 219 H 1.7110 -15.3160 0.4080 H 13 NME 0.271900 + 220 CH3 0.4410 -16.9480 0.5270 CT 13 NME -0.149000 + 221 HH31 -0.3770 -17.3950 -0.0380 H1 13 NME 0.097600 + 222 HH32 1.1090 -17.8030 0.6300 H1 13 NME 0.097600 + 223 HH33 -0.0440 -16.6200 1.4460 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N 0.0940 9.5380 3.0500 N3 1 SER 0.184900 + 2 H1 0.6110 9.5340 2.1830 H 1 SER 0.189800 + 3 H2 -0.6190 10.2450 3.1610 H 1 SER 0.189800 + 4 H3 0.7700 9.6170 3.7970 H 1 SER 0.189800 + 5 CA -0.5410 8.2260 3.2510 CT 1 SER 0.056700 + 6 HA -0.9840 8.2030 4.2470 HP 1 SER 0.078200 + 7 CB -1.5620 7.9760 2.1440 CT 1 SER 0.259600 + 8 HB2 -1.9950 7.0090 2.3990 H1 1 SER 0.027300 + 9 HB3 -0.9920 7.9230 1.2160 H1 1 SER 0.027300 + 10 OG -2.5570 8.9740 2.1030 OH 1 SER -0.671400 + 11 HG -3.2480 8.5930 1.5560 HO 1 SER 0.423900 + 12 C 0.4330 7.0570 3.2610 C 1 SER 0.616300 + 13 O 1.4320 6.9500 2.5520 O 1 SER -0.572200 + 14 N 0.0770 5.9860 3.9740 N 2 TRP -0.415700 + 15 H -0.7990 6.0530 4.4740 H 2 TRP 0.271900 + 16 CA 0.6140 4.6410 4.0210 CT 2 TRP -0.027500 + 17 HA 1.5880 4.7520 4.4960 H1 2 TRP 0.112300 + 18 CB -0.3230 3.8320 4.9130 CT 2 TRP -0.005000 + 19 HB2 -1.2040 3.5870 4.3190 HC 2 TRP 0.033900 + 20 HB3 -0.5210 4.4450 5.7920 HC 2 TRP 0.033900 + 21 CG 0.2020 2.5650 5.5100 C* 2 TRP -0.141500 + 22 CD1 1.5030 2.3530 5.8130 CW 2 TRP -0.163800 + 23 HD1 2.2520 3.0130 5.4020 H4 2 TRP 0.206200 + 24 NE1 1.7100 1.1040 6.3640 NA 2 TRP -0.341800 + 25 HE1 2.5930 0.6160 6.4090 H 2 TRP 0.341200 + 26 CE2 0.5030 0.4710 6.5770 CN 2 TRP 0.138000 + 27 CZ2 0.1640 -0.7780 7.1130 CA 2 TRP -0.260100 + 28 HZ2 0.9130 -1.4800 7.4480 HA 2 TRP 0.157200 + 29 CH2 -1.2000 -1.0020 7.3350 CA 2 TRP -0.113400 + 30 HH2 -1.5150 -1.9100 7.8270 HA 2 TRP 0.141700 + 31 CZ3 -2.1940 -0.1250 6.8860 CA 2 TRP -0.197200 + 32 HZ3 -3.2320 -0.4150 6.9530 HA 2 TRP 0.144700 + 33 CE3 -1.8030 1.0450 6.2240 CA 2 TRP -0.238700 + 34 HE3 -2.5010 1.7520 5.8000 HA 2 TRP 0.170000 + 35 CD2 -0.4530 1.4210 6.1340 CB 2 TRP 0.124300 + 36 C 0.8910 3.9870 2.6750 C 2 TRP 0.597300 + 37 O 1.9900 3.5310 2.3660 O 2 TRP -0.567900 + 38 N -0.0560 4.2220 1.7640 N 3 THR -0.415700 + 39 H -0.8440 4.6380 2.2400 H 3 THR 0.271900 + 40 CA -0.2200 3.7240 0.4130 CT 3 THR -0.038900 + 41 HA -0.2730 2.6360 0.3940 H1 3 THR 0.100700 + 42 CB -1.5400 4.2540 -0.1400 CT 3 THR 0.365400 + 43 HB -1.5870 3.9580 -1.1880 H1 3 THR 0.004300 + 44 CG2 -2.7520 3.5900 0.5080 CT 3 THR -0.243800 + 45 HG21 -2.5160 3.3530 1.5460 HC 3 THR 0.064200 + 46 HG22 -3.5870 4.2780 0.6380 HC 3 THR 0.064200 + 47 HG23 -3.0610 2.6630 0.0250 HC 3 THR 0.064200 + 48 OG1 -1.6540 5.6550 -0.2550 OH 3 THR -0.676100 + 49 HG1 -0.8230 6.1060 -0.0880 HO 3 THR 0.410200 + 50 C 0.9610 4.1900 -0.4270 C 3 THR 0.597300 + 51 O 1.2720 5.3780 -0.4610 O 3 THR -0.567900 + 52 N 1.5440 3.2820 -1.2130 N 4 TRP -0.415700 + 53 H 1.2220 2.3250 -1.1810 H 4 TRP 0.271900 + 54 CA 2.4150 3.6050 -2.3250 CT 4 TRP -0.027500 + 55 HA 2.5860 4.6790 -2.4050 H1 4 TRP 0.112300 + 56 CB 3.7350 2.8440 -2.2430 CT 4 TRP -0.005000 + 57 HB2 3.4360 1.8020 -2.1220 HC 4 TRP 0.033900 + 58 HB3 4.2570 3.0960 -1.3200 HC 4 TRP 0.033900 + 59 CG 4.6580 3.0970 -3.3910 C* 4 TRP -0.141500 + 60 CD1 4.9050 2.2610 -4.4250 CW 4 TRP -0.163800 + 61 HD1 4.3870 1.3320 -4.6080 H4 4 TRP 0.206200 + 62 NE1 5.7670 2.8430 -5.3340 NA 4 TRP -0.341800 + 63 HE1 6.1610 2.3800 -6.1400 H 4 TRP 0.341200 + 64 CE2 6.1930 4.0710 -4.8680 CN 4 TRP 0.138000 + 65 CZ2 7.1420 5.0120 -5.2830 CA 4 TRP -0.260100 + 66 HZ2 7.7380 4.7880 -6.1550 HA 4 TRP 0.157200 + 67 CH2 7.2870 6.2390 -4.6250 CA 4 TRP -0.113400 + 68 HH2 8.0190 6.9740 -4.9250 HA 4 TRP 0.141700 + 69 CZ3 6.6030 6.4110 -3.4150 CA 4 TRP -0.197200 + 70 HZ3 6.7750 7.2880 -2.8100 HA 4 TRP 0.144700 + 71 CE3 5.7230 5.4420 -2.9190 CA 4 TRP -0.238700 + 72 HE3 5.2750 5.5260 -1.9390 HA 4 TRP 0.170000 + 73 CD2 5.5020 4.2600 -3.6430 CB 4 TRP 0.124300 + 74 C 1.6060 3.3600 -3.5910 C 4 TRP 0.597300 + 75 O 1.5440 4.2380 -4.4490 O 4 TRP -0.567900 + 76 N 0.9490 2.2320 -3.8700 N 5 GLU -0.516300 + 77 H 1.0890 1.4360 -3.2650 H 5 GLU 0.293600 + 78 CA -0.0670 1.9690 -4.8690 CT 5 GLU 0.039700 + 79 HA -0.0580 2.7230 -5.6560 H1 5 GLU 0.110500 + 80 CB 0.1390 0.6220 -5.5560 CT 5 GLU 0.056000 + 81 HB2 -0.3100 -0.2180 -5.0260 HC 5 GLU -0.017300 + 82 HB3 1.1780 0.4260 -5.8230 HC 5 GLU -0.017300 + 83 CG -0.4970 0.7060 -6.9400 CT 5 GLU 0.013600 + 84 HG2 0.1020 1.3520 -7.5810 HC 5 GLU -0.042500 + 85 HG3 -1.4670 1.1340 -6.6840 HC 5 GLU -0.042500 + 86 CD -0.7130 -0.6200 -7.6550 C 5 GLU 0.805400 + 87 OE1 0.3370 -1.2340 -7.9410 O2 5 GLU -0.818800 + 88 OE2 -1.7970 -1.2420 -7.6630 O2 5 GLU -0.818800 + 89 C -1.4210 1.9560 -4.1730 C 5 GLU 0.536600 + 90 O -1.6020 1.3750 -3.1050 O 5 GLU -0.581900 + 91 N -2.2190 2.9350 -4.6050 N 6 ASN -0.415700 + 92 H -1.8980 3.3690 -5.4590 H 6 ASN 0.271900 + 93 CA -3.3560 3.5740 -3.9750 CT 6 ASN 0.014300 + 94 HA -3.3290 3.5020 -2.8870 H1 6 ASN 0.104800 + 95 CB -3.2880 5.0970 -4.0500 CT 6 ASN -0.204100 + 96 HB2 -3.3860 5.4630 -5.0720 HC 6 ASN 0.079700 + 97 HB3 -2.3020 5.4100 -3.7070 HC 6 ASN 0.079700 + 98 CG -4.3350 5.7050 -3.1290 C 6 ASN 0.713000 + 99 OD1 -5.3900 6.1540 -3.5730 O 6 ASN -0.593100 + 100 ND2 -4.0990 5.8820 -1.8270 N 6 ASN -0.919100 + 101 HD21 -3.2380 5.6020 -1.3790 H 6 ASN 0.419600 + 102 HD22 -4.7140 6.3660 -1.1880 H 6 ASN 0.419600 + 103 C -4.6540 2.9990 -4.5230 C 6 ASN 0.597300 + 104 O -4.8150 2.7080 -5.7060 O 6 ASN -0.567900 + 105 N -5.4530 2.5630 -3.5470 N 7 GLY -0.415700 + 106 H -5.1070 2.7580 -2.6180 H 7 GLY 0.271900 + 107 CA -6.6720 1.7990 -3.7180 CT 7 GLY -0.025200 + 108 HA2 -6.6560 1.2320 -4.6490 H1 7 GLY 0.069800 + 109 HA3 -7.5310 2.4570 -3.5890 H1 7 GLY 0.069800 + 110 C -6.7350 0.8110 -2.5620 C 7 GLY 0.597300 + 111 O -6.5070 1.1990 -1.4180 O 7 GLY -0.567900 + 112 N -6.9270 -0.4870 -2.8050 N 8 LYS -0.347900 + 113 H -7.2230 -0.7290 -3.7400 H 8 LYS 0.274700 + 114 CA -6.6800 -1.6030 -1.9140 CT 8 LYS -0.240000 + 115 HA -7.0510 -1.4910 -0.8960 H1 8 LYS 0.142600 + 116 CB -7.4490 -2.7920 -2.4830 CT 8 LYS -0.009400 + 117 HB2 -7.2980 -3.5770 -1.7420 HC 8 LYS 0.036200 + 118 HB3 -6.8910 -3.0370 -3.3870 HC 8 LYS 0.036200 + 119 CG -8.9100 -2.7220 -2.9160 CT 8 LYS 0.018700 + 120 HG2 -9.0460 -1.9340 -3.6570 HC 8 LYS 0.010300 + 121 HG3 -9.5100 -2.4240 -2.0560 HC 8 LYS 0.010300 + 122 CD -9.5520 -3.9710 -3.5150 CT 8 LYS -0.047900 + 123 HD2 -8.9980 -4.1970 -4.4260 HC 8 LYS 0.062100 + 124 HD3 -10.6100 -3.7940 -3.7080 HC 8 LYS 0.062100 + 125 CE -9.5690 -5.1540 -2.5520 CT 8 LYS -0.014300 + 126 HE2 -9.8920 -4.7580 -1.5890 HP 8 LYS 0.113500 + 127 HE3 -8.5080 -5.3940 -2.4750 HP 8 LYS 0.113500 + 128 NZ -10.3180 -6.3380 -3.0000 N3 8 LYS -0.385400 + 129 HZ1 -10.4170 -7.0370 -2.2770 H 8 LYS 0.340000 + 130 HZ2 -11.1420 -6.0410 -3.5020 H 8 LYS 0.340000 + 131 HZ3 -9.7910 -6.8710 -3.6780 H 8 LYS 0.340000 + 132 C -5.2010 -1.9260 -1.7500 C 8 LYS 0.734100 + 133 O -4.5550 -2.6110 -2.5390 O 8 LYS -0.589400 + 134 N -4.6160 -1.1980 -0.7960 N 9 TRP -0.415700 + 135 H -5.2470 -0.6060 -0.2740 H 9 TRP 0.271900 + 136 CA -3.2310 -1.3920 -0.4180 CT 9 TRP -0.027500 + 137 HA -2.6130 -1.5850 -1.2940 H1 9 TRP 0.112300 + 138 CB -2.9020 -0.0290 0.1850 CT 9 TRP -0.005000 + 139 HB2 -3.6770 0.2160 0.9110 HC 9 TRP 0.033900 + 140 HB3 -2.9700 0.6790 -0.6410 HC 9 TRP 0.033900 + 141 CG -1.5210 0.0600 0.7500 C* 9 TRP -0.141500 + 142 CD1 -1.2500 0.3150 2.0500 CW 9 TRP -0.163800 + 143 HD1 -1.9330 0.4180 2.8800 H4 9 TRP 0.206200 + 144 NE1 0.1120 0.3910 2.2690 NA 9 TRP -0.341800 + 145 HE1 0.4730 0.4520 3.2100 H 9 TRP 0.341200 + 146 CE2 0.8020 -0.0150 1.1450 CN 9 TRP 0.138000 + 147 CZ2 2.1810 -0.0540 0.9030 CA 9 TRP -0.260100 + 148 HZ2 2.9370 0.0290 1.6700 HA 9 TRP 0.157200 + 149 CH2 2.5480 -0.1620 -0.4440 CA 9 TRP -0.113400 + 150 HH2 3.6010 -0.0910 -0.6750 HA 9 TRP 0.141700 + 151 CZ3 1.6130 -0.3740 -1.4640 CA 9 TRP -0.197200 + 152 HZ3 1.9160 -0.4960 -2.4940 HA 9 TRP 0.144700 + 153 CE3 0.2510 -0.4110 -1.1450 CA 9 TRP -0.238700 + 154 HE3 -0.4010 -0.5540 -1.9940 HA 9 TRP 0.170000 + 155 CD2 -0.2020 -0.0940 0.1460 CB 9 TRP 0.124300 + 156 C -3.0460 -2.4530 0.6580 C 9 TRP 0.597300 + 157 O -3.4300 -2.3600 1.8220 O 9 TRP -0.567900 + 158 N -2.1190 -3.3700 0.3730 N 10 THR -0.415700 + 159 H -1.5230 -3.3090 -0.4410 H 10 THR 0.271900 + 160 CA -1.5920 -4.3360 1.3150 CT 10 THR -0.038900 + 161 HA -2.2000 -4.3200 2.2200 H1 10 THR 0.100700 + 162 CB -1.6110 -5.8200 0.9640 CT 10 THR 0.365400 + 163 HB -1.0800 -6.3360 1.7650 H1 10 THR 0.004300 + 164 CG2 -3.0130 -6.4220 0.9370 CT 10 THR -0.243800 + 165 HG21 -3.7760 -5.7320 1.2990 HC 10 THR 0.064200 + 166 HG22 -3.2090 -6.7400 -0.0870 HC 10 THR 0.064200 + 167 HG23 -2.9840 -7.3040 1.5770 HC 10 THR 0.064200 + 168 OG1 -1.0470 -6.1680 -0.2800 OH 10 THR -0.676100 + 169 HG1 -0.3270 -5.5790 -0.5170 HO 10 THR 0.410200 + 170 C -0.1810 -3.9790 1.7610 C 10 THR 0.597300 + 171 O 0.7490 -4.2310 0.9970 O 10 THR -0.567900 + 172 N -0.0250 -3.4410 2.9730 N 11 TRP -0.415700 + 173 H -0.8450 -3.2600 3.5330 H 11 TRP 0.271900 + 174 CA 1.2920 -3.5070 3.5730 CT 11 TRP -0.027500 + 175 HA 2.0430 -3.0320 2.9400 H1 11 TRP 0.112300 + 176 CB 1.3120 -2.6540 4.8380 CT 11 TRP -0.005000 + 177 HB2 1.2290 -3.3250 5.6920 HC 11 TRP 0.033900 + 178 HB3 0.5960 -1.8320 4.8050 HC 11 TRP 0.033900 + 179 CG 2.6370 -2.0210 5.1160 C* 11 TRP -0.141500 + 180 CD1 3.1350 -0.9320 4.4880 CW 11 TRP -0.163800 + 181 HD1 2.5890 -0.3930 3.7280 H4 11 TRP 0.206200 + 182 NE1 4.4020 -0.6150 4.9380 NA 11 TRP -0.341800 + 183 HE1 4.9790 0.1820 4.7130 H 11 TRP 0.341200 + 184 CE2 4.7860 -1.5810 5.8460 CN 11 TRP 0.138000 + 185 CZ2 5.9410 -1.6940 6.6300 CA 11 TRP -0.260100 + 186 HZ2 6.7870 -1.0630 6.4030 HA 11 TRP 0.157200 + 187 CH2 6.1310 -2.8150 7.4470 CA 11 TRP -0.113400 + 188 HH2 7.0500 -2.9070 8.0070 HA 11 TRP 0.141700 + 189 CZ3 5.0720 -3.7180 7.5990 CA 11 TRP -0.197200 + 190 HZ3 5.2440 -4.6650 8.0890 HA 11 TRP 0.144700 + 191 CE3 3.8660 -3.5310 6.9140 CA 11 TRP -0.238700 + 192 HE3 3.0200 -4.1660 7.1350 HA 11 TRP 0.170000 + 193 CD2 3.6770 -2.4420 6.0490 CB 11 TRP 0.124300 + 194 C 1.7550 -4.9180 3.9060 C 11 TRP 0.597300 + 195 O 1.1090 -5.7330 4.5610 O 11 TRP -0.567900 + 196 N 2.8630 -5.2570 3.2430 N 12 LYS -0.347900 + 197 H 3.2790 -4.5700 2.6300 H 12 LYS 0.274700 + 198 CA 3.6410 -6.4400 3.5500 CT 12 LYS -0.240000 + 199 HA 3.1430 -6.9620 4.3680 H1 12 LYS 0.142600 + 200 CB 3.6760 -7.2910 2.2840 CT 12 LYS -0.009400 + 201 HB2 4.3500 -8.1280 2.4680 HC 12 LYS 0.036200 + 202 HB3 4.0320 -6.7470 1.4090 HC 12 LYS 0.036200 + 203 CG 2.2960 -7.7470 1.8190 CT 12 LYS 0.018700 + 204 HG2 1.8600 -6.9540 1.2110 HC 12 LYS 0.010300 + 205 HG3 1.6870 -8.0280 2.6780 HC 12 LYS 0.010300 + 206 CD 2.2240 -8.9860 0.9320 CT 12 LYS -0.047900 + 207 HD2 2.7370 -9.8630 1.3280 HC 12 LYS 0.062100 + 208 HD3 2.7790 -8.7280 0.0300 HC 12 LYS 0.062100 + 209 CE 0.7820 -9.3120 0.5530 CT 12 LYS -0.014300 + 210 HE2 0.3390 -8.3560 0.2710 HP 12 LYS 0.113500 + 211 HE3 0.2990 -9.6280 1.4780 HP 12 LYS 0.113500 + 212 NZ 0.5810 -10.4460 -0.3620 N3 12 LYS -0.385400 + 213 HZ1 0.7980 -11.3100 0.1130 H 12 LYS 0.340000 + 214 HZ2 -0.3870 -10.5080 -0.6420 H 12 LYS 0.340000 + 215 HZ3 1.0800 -10.3880 -1.2390 H 12 LYS 0.340000 + 216 C 4.9890 -6.1850 4.2100 C 12 LYS 0.734100 + 217 O 5.3240 -6.7970 5.2210 O 12 LYS -0.589400 + 218 N 5.7180 -5.1800 3.7190 N 13 NME -0.415700 + 219 H 5.3890 -4.6800 2.9060 H 13 NME 0.271900 + 220 CH3 6.9980 -4.8110 4.2870 CT 13 NME -0.149000 + 221 HH31 7.2700 -3.7730 4.0930 H1 13 NME 0.097600 + 222 HH32 7.0160 -4.9900 5.3620 H1 13 NME 0.097600 + 223 HH33 7.7550 -5.3990 3.7680 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N 2.5680 12.3590 0.0930 N3 1 SER 0.184900 + 2 H1 2.4520 12.6480 1.0530 H 1 SER 0.189800 + 3 H2 3.4390 11.8470 0.1050 H 1 SER 0.189800 + 4 H3 2.4940 13.1000 -0.5900 H 1 SER 0.189800 + 5 CA 1.4740 11.4380 -0.2520 CT 1 SER 0.056700 + 6 HA 0.5820 12.0120 -0.5030 HP 1 SER 0.078200 + 7 CB 1.7870 10.6040 -1.4910 CT 1 SER 0.259600 + 8 HB2 1.0770 9.8150 -1.7390 H1 1 SER 0.027300 + 9 HB3 2.7160 10.0330 -1.5030 H1 1 SER 0.027300 + 10 OG 1.8050 11.5120 -2.5700 OH 1 SER -0.671400 + 11 HG 1.2410 11.1920 -3.2780 HO 1 SER 0.423900 + 12 C 1.1340 10.4410 0.8460 C 1 SER 0.616300 + 13 O 1.9210 9.5780 1.2290 O 1 SER -0.572200 + 14 N -0.1100 10.5190 1.3250 N 2 TRP -0.415700 + 15 H -0.7350 11.2130 0.9400 H 2 TRP 0.271900 + 16 CA -0.6210 9.6270 2.3460 CT 2 TRP -0.027500 + 17 HA 0.0680 9.6450 3.1910 H1 2 TRP 0.112300 + 18 CB -1.9560 10.1840 2.8310 CT 2 TRP -0.005000 + 19 HB2 -2.6630 10.2240 2.0020 HC 2 TRP 0.033900 + 20 HB3 -1.7570 11.1740 3.2440 HC 2 TRP 0.033900 + 21 CG -2.6340 9.3750 3.8900 C* 2 TRP -0.141500 + 22 CD1 -2.1450 8.5630 4.8540 CW 2 TRP -0.163800 + 23 HD1 -1.0930 8.3340 4.9420 H4 2 TRP 0.206200 + 24 NE1 -3.1320 8.0540 5.6750 NA 2 TRP -0.341800 + 25 HE1 -2.8540 7.5250 6.4890 H 2 TRP 0.341200 + 26 CE2 -4.3440 8.5330 5.2200 CN 2 TRP 0.138000 + 27 CZ2 -5.6430 8.3300 5.7010 CA 2 TRP -0.260100 + 28 HZ2 -5.7890 7.7550 6.6040 HA 2 TRP 0.157200 + 29 CH2 -6.7130 9.0640 5.1760 CA 2 TRP -0.113400 + 30 HH2 -7.7210 8.8180 5.4770 HA 2 TRP 0.141700 + 31 CZ3 -6.4910 9.9980 4.1570 CA 2 TRP -0.197200 + 32 HZ3 -7.3930 10.4420 3.7620 HA 2 TRP 0.144700 + 33 CE3 -5.2020 10.0560 3.6140 CA 2 TRP -0.238700 + 34 HE3 -5.1840 10.4400 2.6050 HA 2 TRP 0.170000 + 35 CD2 -4.0720 9.4070 4.1360 CB 2 TRP 0.124300 + 36 C -0.7150 8.1530 1.9820 C 2 TRP 0.597300 + 37 O -0.2180 7.2160 2.6030 O 2 TRP -0.567900 + 38 N -1.2340 7.9240 0.7730 N 3 THR -0.415700 + 39 H -1.5800 8.6950 0.2190 H 3 THR 0.271900 + 40 CA -1.3990 6.6510 0.1020 CT 3 THR -0.038900 + 41 HA -0.9170 5.8440 0.6530 H1 3 THR 0.100700 + 42 CB -2.8700 6.2770 -0.0560 CT 3 THR 0.365400 + 43 HB -3.0300 5.4690 -0.7700 H1 3 THR 0.004300 + 44 CG2 -3.5410 5.8570 1.2480 CT 3 THR -0.243800 + 45 HG21 -3.8090 6.7030 1.8800 HC 3 THR 0.064200 + 46 HG22 -4.4430 5.2690 1.0770 HC 3 THR 0.064200 + 47 HG23 -2.7990 5.3080 1.8280 HC 3 THR 0.064200 + 48 OG1 -3.6900 7.3330 -0.5060 OH 3 THR -0.676100 + 49 HG1 -3.2660 7.8240 -1.2130 HO 3 THR 0.410200 + 50 C -0.6630 6.6690 -1.2300 C 3 THR 0.597300 + 51 O -1.2490 7.0580 -2.2380 O 3 THR -0.567900 + 52 N 0.5790 6.1830 -1.1700 N 4 TRP -0.415700 + 53 H 0.9870 5.9260 -0.2820 H 4 TRP 0.271900 + 54 CA 1.3900 5.9670 -2.3510 CT 4 TRP -0.027500 + 55 HA 1.2890 6.8610 -2.9660 H1 4 TRP 0.112300 + 56 CB 2.8500 5.7490 -1.9670 CT 4 TRP -0.005000 + 57 HB2 2.9260 4.8660 -1.3310 HC 4 TRP 0.033900 + 58 HB3 3.2520 6.6210 -1.4510 HC 4 TRP 0.033900 + 59 CG 3.6850 5.4910 -3.1800 C* 4 TRP -0.141500 + 60 CD1 4.0950 6.5170 -3.9590 CW 4 TRP -0.163800 + 61 HD1 3.9800 7.5810 -3.8150 H4 4 TRP 0.206200 + 62 NE1 4.9450 6.0410 -4.9390 NA 4 TRP -0.341800 + 63 HE1 5.2850 6.6710 -5.6510 H 4 TRP 0.341200 + 64 CE2 4.9670 4.6610 -4.9620 CN 4 TRP 0.138000 + 65 CZ2 5.4360 3.6970 -5.8630 CA 4 TRP -0.260100 + 66 HZ2 5.9280 3.9440 -6.7920 HA 4 TRP 0.157200 + 67 CH2 5.2070 2.3460 -5.5760 CA 4 TRP -0.113400 + 68 HH2 5.4960 1.6060 -6.3090 HA 4 TRP 0.141700 + 69 CZ3 4.6420 1.9950 -4.3450 CA 4 TRP -0.197200 + 70 HZ3 4.3290 0.9730 -4.1840 HA 4 TRP 0.144700 + 71 CE3 4.1900 2.9490 -3.4250 CA 4 TRP -0.238700 + 72 HE3 3.6870 2.5960 -2.5370 HA 4 TRP 0.170000 + 73 CD2 4.3250 4.3090 -3.7460 CB 4 TRP 0.124300 + 74 C 0.9310 4.8060 -3.2220 C 4 TRP 0.597300 + 75 O 0.9250 4.9430 -4.4440 O 4 TRP -0.567900 + 76 N 0.6050 3.7060 -2.5400 N 5 GLU -0.516300 + 77 H 0.7070 3.7410 -1.5360 H 5 GLU 0.293600 + 78 CA -0.3310 2.7250 -3.0490 CT 5 GLU 0.039700 + 79 HA -0.3320 2.9730 -4.1110 H1 5 GLU 0.110500 + 80 CB 0.2620 1.3700 -2.6720 CT 5 GLU 0.056000 + 81 HB2 -0.2040 1.0320 -1.7470 HC 5 GLU -0.017300 + 82 HB3 1.3510 1.3380 -2.6300 HC 5 GLU -0.017300 + 83 CG -0.1270 0.3600 -3.7480 CT 5 GLU 0.013600 + 84 HG2 0.2170 0.8280 -4.6700 HC 5 GLU -0.042500 + 85 HG3 -1.2030 0.2020 -3.8110 HC 5 GLU -0.042500 + 86 CD 0.4760 -1.0240 -3.5570 C 5 GLU 0.805400 + 87 OE1 1.6160 -1.1670 -4.0500 O2 5 GLU -0.818800 + 88 OE2 -0.1930 -1.8730 -2.9290 O2 5 GLU -0.818800 + 89 C -1.7420 2.9050 -2.5070 C 5 GLU 0.536600 + 90 O -1.9210 3.0310 -1.2980 O 5 GLU -0.581900 + 91 N -2.6790 3.1430 -3.4280 N 6 ASN -0.415700 + 92 H -2.5920 2.8810 -4.3990 H 6 ASN 0.271900 + 93 CA -4.0650 3.4410 -3.1260 CT 6 ASN 0.014300 + 94 HA -3.9240 4.1410 -2.3030 H1 6 ASN 0.104800 + 95 CB -4.6650 4.2250 -4.2900 CT 6 ASN -0.204100 + 96 HB2 -5.3610 3.5720 -4.8190 HC 6 ASN 0.079700 + 97 HB3 -3.8970 4.6230 -4.9520 HC 6 ASN 0.079700 + 98 CG -5.4840 5.4210 -3.8260 C 6 ASN 0.713000 + 99 OD1 -6.2700 5.3410 -2.8850 O 6 ASN -0.593100 + 100 ND2 -5.3640 6.6030 -4.4350 N 6 ASN -0.919100 + 101 HD21 -4.7420 6.7100 -5.2240 H 6 ASN 0.419600 + 102 HD22 -5.7640 7.4310 -4.0170 H 6 ASN 0.419600 + 103 C -4.7510 2.2190 -2.5330 C 6 ASN 0.597300 + 104 O -4.3910 1.0670 -2.7640 O 6 ASN -0.567900 + 105 N -5.7230 2.5060 -1.6640 N 7 GLY -0.415700 + 106 H -5.8760 3.4590 -1.3680 H 7 GLY 0.271900 + 107 CA -6.5190 1.4880 -1.0070 CT 7 GLY -0.025200 + 108 HA2 -7.0480 0.8370 -1.7030 H1 7 GLY 0.069800 + 109 HA3 -7.2680 1.9040 -0.3330 H1 7 GLY 0.069800 + 110 C -5.6480 0.5550 -0.1790 C 7 GLY 0.597300 + 111 O -4.8170 1.0730 0.5640 O 7 GLY -0.567900 + 112 N -5.7610 -0.7740 -0.2370 N 8 LYS -0.347900 + 113 H -6.5070 -1.1000 -0.8340 H 8 LYS 0.274700 + 114 CA -5.1460 -1.7160 0.6770 CT 8 LYS -0.240000 + 115 HA -5.1270 -1.3090 1.6880 H1 8 LYS 0.142600 + 116 CB -6.0850 -2.9180 0.6270 CT 8 LYS -0.009400 + 117 HB2 -5.5930 -3.7470 1.1380 HC 8 LYS 0.036200 + 118 HB3 -6.3050 -3.1020 -0.4240 HC 8 LYS 0.036200 + 119 CG -7.4230 -2.7380 1.3370 CT 8 LYS 0.018700 + 120 HG2 -7.9280 -1.9520 0.7750 HC 8 LYS 0.010300 + 121 HG3 -7.2810 -2.3880 2.3590 HC 8 LYS 0.010300 + 122 CD -8.2550 -4.0080 1.1840 CT 8 LYS -0.047900 + 123 HD2 -7.9580 -4.6940 1.9770 HC 8 LYS 0.062100 + 124 HD3 -8.0580 -4.4660 0.2150 HC 8 LYS 0.062100 + 125 CE -9.7430 -3.7230 1.3700 CT 8 LYS -0.014300 + 126 HE2 -10.0110 -3.1490 0.4830 HP 8 LYS 0.113500 + 127 HE3 -9.8560 -3.0290 2.2020 HP 8 LYS 0.113500 + 128 NZ -10.5970 -4.9150 1.4860 N3 8 LYS -0.385400 + 129 HZ1 -11.5440 -4.6690 1.2360 H 8 LYS 0.340000 + 130 HZ2 -10.1950 -5.5770 0.8390 H 8 LYS 0.340000 + 131 HZ3 -10.5230 -5.3640 2.3880 H 8 LYS 0.340000 + 132 C -3.7030 -2.1350 0.4330 C 8 LYS 0.734100 + 133 O -3.3980 -2.5010 -0.6990 O 8 LYS -0.589400 + 134 N -2.8370 -2.1440 1.4500 N 9 TRP -0.415700 + 135 H -3.2660 -1.8890 2.3280 H 9 TRP 0.271900 + 136 CA -1.4700 -2.6120 1.3410 CT 9 TRP -0.027500 + 137 HA -0.9110 -2.4110 0.4270 H1 9 TRP 0.112300 + 138 CB -0.6970 -1.8800 2.4340 CT 9 TRP -0.005000 + 139 HB2 -1.1700 -2.2050 3.3600 HC 9 TRP 0.033900 + 140 HB3 -0.7590 -0.7960 2.3390 HC 9 TRP 0.033900 + 141 CG 0.7540 -2.1150 2.7070 C* 9 TRP -0.141500 + 142 CD1 1.3100 -2.4420 3.8960 CW 9 TRP -0.163800 + 143 HD1 0.7430 -2.4140 4.8140 H4 9 TRP 0.206200 + 144 NE1 2.6710 -2.6170 3.7440 NA 9 TRP -0.341800 + 145 HE1 3.2160 -2.8110 4.5720 H 9 TRP 0.341200 + 146 CE2 3.0490 -2.2770 2.4610 CN 9 TRP 0.138000 + 147 CZ2 4.3240 -2.3840 1.8930 CA 9 TRP -0.260100 + 148 HZ2 5.2410 -2.5570 2.4360 HA 9 TRP 0.157200 + 149 CH2 4.4740 -2.0090 0.5520 CA 9 TRP -0.113400 + 150 HH2 5.5070 -1.9800 0.2390 HA 9 TRP 0.141700 + 151 CZ3 3.3440 -1.6840 -0.2070 CA 9 TRP -0.197200 + 152 HZ3 3.4230 -1.5230 -1.2720 HA 9 TRP 0.144700 + 153 CE3 2.0780 -1.7830 0.3830 CA 9 TRP -0.238700 + 154 HE3 1.2270 -1.5610 -0.2430 HA 9 TRP 0.170000 + 155 CD2 1.8470 -2.0440 1.7430 CB 9 TRP 0.124300 + 156 C -1.3820 -4.1250 1.4810 C 9 TRP 0.597300 + 157 O -1.3300 -4.6880 2.5720 O 9 TRP -0.567900 + 158 N -1.5080 -4.8160 0.3460 N 10 THR -0.415700 + 159 H -1.4630 -4.3840 -0.5660 H 10 THR 0.271900 + 160 CA -1.1440 -6.2190 0.3410 CT 10 THR -0.038900 + 161 HA -1.8110 -6.7080 1.0500 H1 10 THR 0.100700 + 162 CB -1.3370 -6.9320 -0.9940 CT 10 THR 0.365400 + 163 HB -1.0100 -7.9700 -0.9320 H1 10 THR 0.004300 + 164 CG2 -2.8370 -6.9880 -1.2690 CT 10 THR -0.243800 + 165 HG21 -3.0490 -5.9310 -1.4260 HC 10 THR 0.064200 + 166 HG22 -3.0930 -7.4340 -2.2300 HC 10 THR 0.064200 + 167 HG23 -3.2920 -7.4700 -0.4030 HC 10 THR 0.064200 + 168 OG1 -0.6650 -6.3420 -2.0850 OH 10 THR -0.676100 + 169 HG1 -1.0290 -6.7400 -2.8800 HO 10 THR 0.410200 + 170 C 0.2210 -6.5310 0.9390 C 10 THR 0.597300 + 171 O 1.2720 -6.1100 0.4610 O 10 THR -0.567900 + 172 N 0.1500 -7.2510 2.0610 N 11 TRP -0.415700 + 173 H -0.7370 -7.5370 2.4510 H 11 TRP 0.271900 + 174 CA 1.2940 -7.9120 2.6540 CT 11 TRP -0.027500 + 175 HA 1.8970 -7.0870 3.0340 H1 11 TRP 0.112300 + 176 CB 0.7440 -8.6050 3.8970 CT 11 TRP -0.005000 + 177 HB2 0.3160 -9.5760 3.6490 HC 11 TRP 0.033900 + 178 HB3 -0.0950 -8.0490 4.3160 HC 11 TRP 0.033900 + 179 CG 1.7590 -8.8560 4.9660 C* 11 TRP -0.141500 + 180 CD1 2.1020 -7.9870 5.9430 CW 11 TRP -0.163800 + 181 HD1 1.6360 -7.0200 6.0620 H4 11 TRP 0.206200 + 182 NE1 3.2700 -8.4370 6.5260 NA 11 TRP -0.341800 + 183 HE1 3.6120 -8.1090 7.4180 H 11 TRP 0.341200 + 184 CE2 3.6120 -9.6990 6.0830 CN 11 TRP 0.138000 + 185 CZ2 4.4720 -10.7340 6.4680 CA 11 TRP -0.260100 + 186 HZ2 5.1160 -10.8350 7.3300 HA 11 TRP 0.157200 + 187 CH2 4.5160 -11.9490 5.7740 CA 11 TRP -0.113400 + 188 HH2 5.2680 -12.6640 6.0730 HA 11 TRP 0.141700 + 189 CZ3 3.6270 -12.2020 4.7220 CA 11 TRP -0.197200 + 190 HZ3 3.6240 -13.0850 4.1010 HA 11 TRP 0.144700 + 191 CE3 2.7960 -11.1600 4.2940 CA 11 TRP -0.238700 + 192 HE3 2.1260 -11.4320 3.4920 HA 11 TRP 0.170000 + 193 CD2 2.7060 -9.9640 5.0230 CB 11 TRP 0.124300 + 194 C 2.2050 -8.7470 1.7660 C 11 TRP 0.597300 + 195 O 1.7170 -9.7200 1.1960 O 11 TRP -0.567900 + 196 N 3.4990 -8.4290 1.8490 N 12 LYS -0.347900 + 197 H 3.7020 -7.5930 2.3770 H 12 LYS 0.274700 + 198 CA 4.5550 -9.1850 1.2060 CT 12 LYS -0.240000 + 199 HA 4.1150 -9.8690 0.4800 H1 12 LYS 0.142600 + 200 CB 5.4900 -8.1870 0.5290 CT 12 LYS -0.009400 + 201 HB2 6.2940 -8.8110 0.1400 HC 12 LYS 0.036200 + 202 HB3 5.7640 -7.3570 1.1810 HC 12 LYS 0.036200 + 203 CG 4.7910 -7.5370 -0.6610 CT 12 LYS 0.018700 + 204 HG2 3.9210 -7.0310 -0.2420 HC 12 LYS 0.010300 + 205 HG3 4.5470 -8.3270 -1.3710 HC 12 LYS 0.010300 + 206 CD 5.6030 -6.4730 -1.3950 CT 12 LYS -0.047900 + 207 HD2 5.6910 -5.6540 -0.6820 HC 12 LYS 0.062100 + 208 HD3 4.9000 -6.1680 -2.1710 HC 12 LYS 0.062100 + 209 CE 6.9770 -6.9350 -1.8700 CT 12 LYS -0.014300 + 210 HE2 6.8710 -7.8940 -2.3760 HP 12 LYS 0.113500 + 211 HE3 7.5210 -7.2920 -0.9950 HP 12 LYS 0.113500 + 212 NZ 7.6300 -5.9360 -2.7310 N3 12 LYS -0.385400 + 213 HZ1 7.1600 -5.9920 -3.6230 H 12 LYS 0.340000 + 214 HZ2 7.7390 -5.0680 -2.2270 H 12 LYS 0.340000 + 215 HZ3 8.5080 -6.2730 -3.0990 H 12 LYS 0.340000 + 216 C 5.3320 -10.1440 2.0970 C 12 LYS 0.734100 + 217 O 5.3550 -11.2770 1.6220 O 12 LYS -0.589400 + 218 N 5.8320 -9.7320 3.2630 N 13 NME -0.415700 + 219 H 5.5630 -8.7890 3.5060 H 13 NME 0.271900 + 220 CH3 6.9330 -10.2970 4.0170 CT 13 NME -0.149000 + 221 HH31 7.7560 -9.5830 3.9870 H1 13 NME 0.097600 + 222 HH32 6.7090 -10.3500 5.0820 H1 13 NME 0.097600 + 223 HH33 7.4080 -11.1820 3.5940 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -3.5310 2.5650 1.7360 N3 1 SER 0.184900 + 2 H1 -2.8050 2.4120 1.0510 H 1 SER 0.189800 + 3 H2 -4.2920 1.9410 1.5070 H 1 SER 0.189800 + 4 H3 -3.7540 3.5360 1.5730 H 1 SER 0.189800 + 5 CA -2.9110 2.2850 3.0400 CT 1 SER 0.056700 + 6 HA -3.5710 2.3240 3.9070 HP 1 SER 0.078200 + 7 CB -2.7170 0.7760 3.1560 CT 1 SER 0.259600 + 8 HB2 -3.6960 0.3000 3.1980 H1 1 SER 0.027300 + 9 HB3 -2.2090 0.5840 4.1010 H1 1 SER 0.027300 + 10 OG -1.9710 0.2640 2.0740 OH 1 SER -0.671400 + 11 HG -1.8570 -0.6870 2.1330 HO 1 SER 0.423900 + 12 C -1.6560 3.0270 3.4790 C 1 SER 0.616300 + 13 O -1.6530 3.8510 4.3900 O 1 SER -0.572200 + 14 N -0.6160 2.9720 2.6430 N 2 TRP -0.415700 + 15 H -0.6490 2.2730 1.9150 H 2 TRP 0.271900 + 16 CA 0.5960 3.7640 2.6920 CT 2 TRP -0.027500 + 17 HA 0.6630 4.2520 3.6650 H1 2 TRP 0.112300 + 18 CB 1.8870 2.9530 2.6180 CT 2 TRP -0.005000 + 19 HB2 2.0590 2.5540 1.6190 HC 2 TRP 0.033900 + 20 HB3 1.7590 2.0690 3.2430 HC 2 TRP 0.033900 + 21 CG 3.1350 3.5590 3.1740 C* 2 TRP -0.141500 + 22 CD1 3.4720 3.6970 4.4760 CW 2 TRP -0.163800 + 23 HD1 2.9910 3.4710 5.4160 H4 2 TRP 0.206200 + 24 NE1 4.6320 4.4420 4.5540 NA 2 TRP -0.341800 + 25 HE1 4.8550 4.8220 5.4630 H 2 TRP 0.341200 + 26 CE2 5.2520 4.6030 3.3320 CN 2 TRP 0.138000 + 27 CZ2 6.4820 5.0730 2.8570 CA 2 TRP -0.260100 + 28 HZ2 7.1870 5.4570 3.5790 HA 2 TRP 0.157200 + 29 CH2 6.7750 5.0910 1.4880 CA 2 TRP -0.113400 + 30 HH2 7.7060 5.5450 1.1830 HA 2 TRP 0.141700 + 31 CZ3 5.7830 4.6090 0.6240 CA 2 TRP -0.197200 + 32 HZ3 5.8640 4.5640 -0.4520 HA 2 TRP 0.144700 + 33 CE3 4.5030 4.2450 1.0600 CA 2 TRP -0.238700 + 34 HE3 3.7760 3.8770 0.3520 HA 2 TRP 0.170000 + 35 CD2 4.2510 4.1440 2.4380 CB 2 TRP 0.124300 + 36 C 0.6760 4.9450 1.7350 C 2 TRP 0.597300 + 37 O 1.1990 6.0190 2.0240 O 2 TRP -0.567900 + 38 N 0.1140 4.6930 0.5510 N 3 THR -0.415700 + 39 H -0.2350 3.7870 0.2720 H 3 THR 0.271900 + 40 CA -0.1510 5.6140 -0.5360 CT 3 THR -0.038900 + 41 HA 0.7770 6.1390 -0.7590 H1 3 THR 0.100700 + 42 CB -0.3440 4.7970 -1.8110 CT 3 THR 0.365400 + 43 HB -0.5770 5.5250 -2.5880 H1 3 THR 0.004300 + 44 CG2 0.8000 3.8830 -2.2430 CT 3 THR -0.243800 + 45 HG21 1.7240 4.4020 -1.9900 HC 3 THR 0.064200 + 46 HG22 0.7300 2.9530 -1.6800 HC 3 THR 0.064200 + 47 HG23 0.7820 3.7570 -3.3260 HC 3 THR 0.064200 + 48 OG1 -1.3690 3.8300 -1.7650 OH 3 THR -0.676100 + 49 HG1 -1.2320 3.1890 -2.4670 HO 3 THR 0.410200 + 50 C -1.2240 6.6490 -0.2330 C 3 THR 0.597300 + 51 O -2.2450 6.2180 0.2990 O 3 THR -0.567900 + 52 N -0.9180 7.8940 -0.6080 N 4 TRP -0.415700 + 53 H 0.0280 8.0910 -0.9020 H 4 TRP 0.271900 + 54 CA -1.7840 8.9790 -0.1930 CT 4 TRP -0.027500 + 55 HA -1.7960 9.1440 0.8850 H1 4 TRP 0.112300 + 56 CB -1.2670 10.2680 -0.8240 CT 4 TRP -0.005000 + 57 HB2 -1.9970 11.0260 -0.5420 HC 4 TRP 0.033900 + 58 HB3 -1.1920 10.1610 -1.9060 HC 4 TRP 0.033900 + 59 CG 0.0350 10.8210 -0.3380 C* 4 TRP -0.141500 + 60 CD1 1.1780 10.8810 -1.0570 CW 4 TRP -0.163800 + 61 HD1 1.3670 10.6930 -2.1030 H4 4 TRP 0.206200 + 62 NE1 2.2050 11.2620 -0.2160 NA 4 TRP -0.341800 + 63 HE1 3.1690 11.3090 -0.5130 H 4 TRP 0.341200 + 64 CE2 1.7670 11.5270 1.0660 CN 4 TRP 0.138000 + 65 CZ2 2.3930 12.1140 2.1720 CA 4 TRP -0.260100 + 66 HZ2 3.4470 12.3460 2.2080 HA 4 TRP 0.157200 + 67 CH2 1.5870 12.3770 3.2870 CA 4 TRP -0.113400 + 68 HH2 2.0320 12.8430 4.1540 HA 4 TRP 0.141700 + 69 CZ3 0.2110 12.1190 3.2960 CA 4 TRP -0.197200 + 70 HZ3 -0.4070 12.3330 4.1550 HA 4 TRP 0.144700 + 71 CE3 -0.3860 11.5790 2.1500 CA 4 TRP -0.238700 + 72 HE3 -1.4500 11.4050 2.1990 HA 4 TRP 0.170000 + 73 CD2 0.3640 11.3280 0.9900 CB 4 TRP 0.124300 + 74 C -3.2230 8.7600 -0.6360 C 4 TRP 0.597300 + 75 O -4.1570 8.9510 0.1400 O 4 TRP -0.567900 + 76 N -3.4490 8.3780 -1.8950 N 5 GLU -0.516300 + 77 H -2.6060 8.3020 -2.4460 H 5 GLU 0.293600 + 78 CA -4.6550 7.8800 -2.5250 CT 5 GLU 0.039700 + 79 HA -5.5720 7.8820 -1.9350 H1 5 GLU 0.110500 + 80 CB -4.9450 8.5950 -3.8420 CT 5 GLU 0.056000 + 81 HB2 -4.0960 8.4810 -4.5160 HC 5 GLU -0.017300 + 82 HB3 -4.9280 9.6700 -3.6630 HC 5 GLU -0.017300 + 83 CG -6.2030 8.1410 -4.5770 CT 5 GLU 0.013600 + 84 HG2 -6.1980 7.0510 -4.5960 HC 5 GLU -0.042500 + 85 HG3 -6.1750 8.4640 -5.6180 HC 5 GLU -0.042500 + 86 CD -7.4790 8.7570 -4.0210 C 5 GLU 0.805400 + 87 OE1 -7.6760 8.8470 -2.7900 O2 5 GLU -0.818800 + 88 OE2 -8.3190 9.1810 -4.8440 O2 5 GLU -0.818800 + 89 C -4.2650 6.4230 -2.7240 C 5 GLU 0.536600 + 90 O -3.3580 6.0620 -3.4710 O 5 GLU -0.581900 + 91 N -5.0250 5.5900 -2.0100 N 6 ASN -0.415700 + 92 H -5.7670 6.0050 -1.4650 H 6 ASN 0.271900 + 93 CA -5.0610 4.1430 -2.0820 CT 6 ASN 0.014300 + 94 HA -4.2100 3.7150 -1.5530 H1 6 ASN 0.104800 + 95 CB -6.3730 3.7870 -1.3870 CT 6 ASN -0.204100 + 96 HB2 -7.2540 4.0820 -1.9570 HC 6 ASN 0.079700 + 97 HB3 -6.4110 4.2120 -0.3840 HC 6 ASN 0.079700 + 98 CG -6.3430 2.2950 -1.0880 C 6 ASN 0.713000 + 99 OD1 -5.8200 1.8160 -0.0850 O 6 ASN -0.593100 + 100 ND2 -6.7740 1.5360 -2.0970 N 6 ASN -0.919100 + 101 HD21 -7.0090 1.8800 -3.0170 H 6 ASN 0.419600 + 102 HD22 -6.7730 0.5310 -1.9940 H 6 ASN 0.419600 + 103 C -4.9690 3.7060 -3.5370 C 6 ASN 0.597300 + 104 O -5.8020 4.0490 -4.3730 O 6 ASN -0.567900 + 105 N -3.8850 2.9850 -3.8320 N 7 GLY -0.415700 + 106 H -3.1820 3.0260 -3.1080 H 7 GLY 0.271900 + 107 CA -3.5710 2.0450 -4.8890 CT 7 GLY -0.025200 + 108 HA2 -2.9950 2.5330 -5.6750 H1 7 GLY 0.069800 + 109 HA3 -4.5160 1.8340 -5.3900 H1 7 GLY 0.069800 + 110 C -3.1590 0.6510 -4.4390 C 7 GLY 0.597300 + 111 O -3.8060 0.0600 -3.5770 O 7 GLY -0.567900 + 112 N -2.2110 0.0490 -5.1600 N 8 LYS -0.347900 + 113 H -1.7170 0.6110 -5.8390 H 8 LYS 0.274700 + 114 CA -1.7290 -1.2920 -4.9000 CT 8 LYS -0.240000 + 115 HA -2.6060 -1.8260 -4.5320 H1 8 LYS 0.142600 + 116 CB -1.0900 -1.9210 -6.1340 CT 8 LYS -0.009400 + 117 HB2 -1.7530 -2.0170 -6.9940 HC 8 LYS 0.036200 + 118 HB3 -0.8290 -2.9270 -5.8060 HC 8 LYS 0.036200 + 119 CG 0.1160 -1.1210 -6.6190 CT 8 LYS 0.018700 + 120 HG2 0.8500 -1.1190 -5.8140 HC 8 LYS 0.010300 + 121 HG3 -0.1890 -0.0820 -6.7430 HC 8 LYS 0.010300 + 122 CD 0.9040 -1.6960 -7.7930 CT 8 LYS -0.047900 + 123 HD2 0.1820 -1.8710 -8.5910 HC 8 LYS 0.062100 + 124 HD3 1.3950 -2.5760 -7.3790 HC 8 LYS 0.062100 + 125 CE 1.8810 -0.7430 -8.4750 CT 8 LYS -0.014300 + 126 HE2 2.6960 -0.5520 -7.7770 HP 8 LYS 0.113500 + 127 HE3 1.3070 0.1580 -8.6930 HP 8 LYS 0.113500 + 128 NZ 2.4270 -1.2470 -9.7450 N3 8 LYS -0.385400 + 129 HZ1 1.7010 -1.5710 -10.3680 H 8 LYS 0.340000 + 130 HZ2 2.9780 -0.5180 -10.1750 H 8 LYS 0.340000 + 131 HZ3 2.9960 -2.0540 -9.5320 H 8 LYS 0.340000 + 132 C -0.8770 -1.4670 -3.6510 C 8 LYS 0.734100 + 133 O -0.0600 -0.6160 -3.3030 O 8 LYS -0.589400 + 134 N -1.1830 -2.4230 -2.7710 N 9 TRP -0.415700 + 135 H -2.0990 -2.8170 -2.9290 H 9 TRP 0.271900 + 136 CA -0.3610 -2.9160 -1.6840 CT 9 TRP -0.027500 + 137 HA 0.6240 -2.4770 -1.8400 H1 9 TRP 0.112300 + 138 CB -0.8140 -2.3870 -0.3260 CT 9 TRP -0.005000 + 139 HB2 -1.7940 -2.8020 -0.0920 HC 9 TRP 0.033900 + 140 HB3 -0.8900 -1.3050 -0.4340 HC 9 TRP 0.033900 + 141 CG 0.0910 -2.7410 0.8110 C* 9 TRP -0.141500 + 142 CD1 -0.2990 -3.2490 2.0010 CW 9 TRP -0.163800 + 143 HD1 -1.2930 -3.5640 2.2810 H4 9 TRP 0.206200 + 144 NE1 0.8200 -3.2760 2.8100 NA 9 TRP -0.341800 + 145 HE1 0.8270 -3.4920 3.7970 H 9 TRP 0.341200 + 146 CE2 1.9240 -2.7540 2.1670 CN 9 TRP 0.138000 + 147 CZ2 3.2370 -2.5330 2.6010 CA 9 TRP -0.260100 + 148 HZ2 3.4990 -2.8690 3.5930 HA 9 TRP 0.157200 + 149 CH2 4.2230 -2.2110 1.6610 CA 9 TRP -0.113400 + 150 HH2 5.2140 -2.0560 2.0620 HA 9 TRP 0.141700 + 151 CZ3 3.8620 -1.9280 0.3380 CA 9 TRP -0.197200 + 152 HZ3 4.5440 -1.5490 -0.4080 HA 9 TRP 0.144700 + 153 CE3 2.5040 -1.9200 -0.0020 CA 9 TRP -0.238700 + 154 HE3 2.2760 -1.5630 -0.9960 HA 9 TRP 0.170000 + 155 CD2 1.5280 -2.4920 0.8300 CB 9 TRP 0.124300 + 156 C -0.1210 -4.4180 -1.7140 C 9 TRP 0.597300 + 157 O -1.0110 -5.1810 -2.0850 O 9 TRP -0.567900 + 158 N 1.0810 -4.9090 -1.4040 N 10 THR -0.415700 + 159 H 1.7490 -4.1530 -1.3520 H 10 THR 0.271900 + 160 CA 1.4460 -6.2720 -1.0750 CT 10 THR -0.038900 + 161 HA 0.7610 -6.9630 -1.5660 H1 10 THR 0.100700 + 162 CB 2.8400 -6.7060 -1.5210 CT 10 THR 0.365400 + 163 HB 3.5860 -5.9210 -1.3950 H1 10 THR 0.004300 + 164 CG2 3.5150 -7.9550 -0.9630 CT 10 THR -0.243800 + 165 HG21 4.3120 -8.3240 -1.6090 HC 10 THR 0.064200 + 166 HG22 3.9130 -7.7510 0.0310 HC 10 THR 0.064200 + 167 HG23 2.7020 -8.6580 -0.7790 HC 10 THR 0.064200 + 168 OG1 2.7230 -6.8810 -2.9150 OH 10 THR -0.676100 + 169 HG1 2.2690 -6.0760 -3.1760 HO 10 THR 0.410200 + 170 C 1.3880 -6.3870 0.4420 C 10 THR 0.597300 + 171 O 2.2170 -5.7830 1.1190 O 10 THR -0.567900 + 172 N 0.5700 -7.3560 0.8600 N 11 TRP -0.415700 + 173 H 0.1200 -7.9160 0.1500 H 11 TRP 0.271900 + 174 CA 0.5690 -7.8270 2.2300 CT 11 TRP -0.027500 + 175 HA 0.9270 -7.0630 2.9190 H1 11 TRP 0.112300 + 176 CB -0.8290 -8.2510 2.6740 CT 11 TRP -0.005000 + 177 HB2 -1.2150 -9.0110 1.9950 HC 11 TRP 0.033900 + 178 HB3 -1.5210 -7.4350 2.4650 HC 11 TRP 0.033900 + 179 CG -1.0700 -8.7580 4.0590 C* 11 TRP -0.141500 + 180 CD1 -0.8460 -8.0030 5.1580 CW 11 TRP -0.163800 + 181 HD1 -0.4450 -7.0000 5.1720 H4 11 TRP 0.206200 + 182 NE1 -0.9930 -8.8480 6.2410 NA 11 TRP -0.341800 + 183 HE1 -0.7550 -8.6630 7.2050 H 11 TRP 0.341200 + 184 CE2 -1.5370 -10.0560 5.8560 CN 11 TRP 0.138000 + 185 CZ2 -2.0590 -11.1270 6.5920 CA 11 TRP -0.260100 + 186 HZ2 -2.0030 -11.1010 7.6700 HA 11 TRP 0.157200 + 187 CH2 -2.4860 -12.3000 5.9590 CA 11 TRP -0.113400 + 188 HH2 -2.8920 -13.1670 6.4600 HA 11 TRP 0.141700 + 189 CZ3 -2.5150 -12.2700 4.5590 CA 11 TRP -0.197200 + 190 HZ3 -2.8620 -13.1380 4.0190 HA 11 TRP 0.144700 + 191 CE3 -2.1370 -11.1750 3.7730 CA 11 TRP -0.238700 + 192 HE3 -2.3570 -11.1380 2.7170 HA 11 TRP 0.170000 + 193 CD2 -1.5720 -10.0740 4.4380 CB 11 TRP 0.124300 + 194 C 1.5870 -8.9490 2.3750 C 11 TRP 0.597300 + 195 O 1.3030 -10.0720 1.9630 O 11 TRP -0.567900 + 196 N 2.6680 -8.6980 3.1160 N 12 LYS -0.347900 + 197 H 2.7820 -7.7780 3.5160 H 12 LYS 0.274700 + 198 CA 3.6030 -9.7480 3.4680 CT 12 LYS -0.240000 + 199 HA 3.8470 -10.4680 2.6870 H1 12 LYS 0.142600 + 200 CB 4.8410 -9.0850 4.0650 CT 12 LYS -0.009400 + 201 HB2 5.4420 -9.8900 4.4880 HC 12 LYS 0.036200 + 202 HB3 4.4280 -8.4350 4.8360 HC 12 LYS 0.036200 + 203 CG 5.7990 -8.4830 3.0410 CT 12 LYS 0.018700 + 204 HG2 5.4320 -7.5810 2.5530 HC 12 LYS 0.010300 + 205 HG3 6.0510 -9.2440 2.3020 HC 12 LYS 0.010300 + 206 CD 7.1220 -8.1650 3.7330 CT 12 LYS -0.047900 + 207 HD2 6.9520 -7.1810 4.1710 HC 12 LYS 0.062100 + 208 HD3 7.9000 -8.0900 2.9730 HC 12 LYS 0.062100 + 209 CE 7.7460 -9.0090 4.8400 CT 12 LYS -0.014300 + 210 HE2 7.8050 -10.0300 4.4620 HP 12 LYS 0.113500 + 211 HE3 7.0010 -8.9610 5.6340 HP 12 LYS 0.113500 + 212 NZ 9.0180 -8.3730 5.2130 N3 12 LYS -0.385400 + 213 HZ1 9.6910 -8.5380 4.4780 H 12 LYS 0.340000 + 214 HZ2 8.8820 -7.3770 5.3150 H 12 LYS 0.340000 + 215 HZ3 9.4210 -8.8250 6.0210 H 12 LYS 0.340000 + 216 C 3.0230 -10.6330 4.5620 C 12 LYS 0.734100 + 217 O 3.1090 -11.8570 4.5020 O 12 LYS -0.589400 + 218 N 2.5200 -10.0560 5.6560 N 13 NME -0.415700 + 219 H 2.2580 -9.1020 5.4520 H 13 NME 0.271900 + 220 CH3 2.1240 -10.7870 6.8430 CT 13 NME -0.149000 + 221 HH31 3.0170 -11.3400 7.1330 H1 13 NME 0.097600 + 222 HH32 1.9400 -10.0090 7.5830 H1 13 NME 0.097600 + 223 HH33 1.1890 -11.3340 6.7210 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -1.1360 7.1690 4.5850 N3 1 SER 0.184900 + 2 H1 -0.2300 6.8990 4.2310 H 1 SER 0.189800 + 3 H2 -1.5070 6.2980 4.9370 H 1 SER 0.189800 + 4 H3 -1.5490 7.4520 3.7070 H 1 SER 0.189800 + 5 CA -0.8450 8.2170 5.5750 CT 1 SER 0.056700 + 6 HA -1.7650 8.6970 5.9090 HP 1 SER 0.078200 + 7 CB -0.3220 7.6540 6.8930 CT 1 SER 0.259600 + 8 HB2 -1.2560 7.2770 7.3100 H1 1 SER 0.027300 + 9 HB3 0.0230 8.4730 7.5230 H1 1 SER 0.027300 + 10 OG 0.6280 6.6150 6.8030 OH 1 SER -0.671400 + 11 HG 0.8230 6.3380 7.7010 HO 1 SER 0.423900 + 12 C 0.0950 9.2770 5.0190 C 1 SER 0.616300 + 13 O -0.3080 10.4170 4.7960 O 1 SER -0.572200 + 14 N 1.3800 8.9720 4.8200 N 2 TRP -0.415700 + 15 H 1.6820 8.1050 5.2410 H 2 TRP 0.271900 + 16 CA 2.3570 9.8440 4.2010 CT 2 TRP -0.027500 + 17 HA 2.0880 10.8500 4.5210 H1 2 TRP 0.112300 + 18 CB 3.7360 9.3980 4.6790 CT 2 TRP -0.005000 + 19 HB2 4.0180 8.3820 4.4030 HC 2 TRP 0.033900 + 20 HB3 3.7010 9.3540 5.7680 HC 2 TRP 0.033900 + 21 CG 4.8170 10.3860 4.3770 C* 2 TRP -0.141500 + 22 CD1 5.0360 11.3990 5.2450 CW 2 TRP -0.163800 + 23 HD1 4.5800 11.6280 6.1970 H4 2 TRP 0.206200 + 24 NE1 6.0630 12.1710 4.7380 NA 2 TRP -0.341800 + 25 HE1 6.4290 12.9660 5.2430 H 2 TRP 0.341200 + 26 CE2 6.3960 11.7640 3.4620 CN 2 TRP 0.138000 + 27 CZ2 7.2290 12.3900 2.5270 CA 2 TRP -0.260100 + 28 HZ2 7.8910 13.1840 2.8360 HA 2 TRP 0.157200 + 29 CH2 7.4410 11.7280 1.3120 CA 2 TRP -0.113400 + 30 HH2 8.1220 12.2630 0.6670 HA 2 TRP 0.141700 + 31 CZ3 6.5690 10.6820 0.9870 CA 2 TRP -0.197200 + 32 HZ3 6.7150 10.2320 0.0160 HA 2 TRP 0.144700 + 33 CE3 5.6520 10.1000 1.8700 CA 2 TRP -0.238700 + 34 HE3 4.9880 9.3010 1.5740 HA 2 TRP 0.170000 + 35 CD2 5.6070 10.6200 3.1730 CB 2 TRP 0.124300 + 36 C 2.2880 9.7790 2.6820 C 2 TRP 0.597300 + 37 O 2.4180 10.7850 1.9880 O 2 TRP -0.567900 + 38 N 1.9390 8.5900 2.1850 N 3 THR -0.415700 + 39 H 1.9120 7.8220 2.8400 H 3 THR 0.271900 + 40 CA 1.6810 8.3030 0.7880 CT 3 THR -0.038900 + 41 HA 2.1380 9.0050 0.0900 H1 3 THR 0.100700 + 42 CB 2.2780 6.9410 0.4470 CT 3 THR 0.365400 + 43 HB 1.8780 6.6510 -0.5250 H1 3 THR 0.004300 + 44 CG2 3.7950 6.9780 0.2890 CT 3 THR -0.243800 + 45 HG21 4.0800 7.7810 -0.3910 HC 3 THR 0.064200 + 46 HG22 4.2530 7.0370 1.2760 HC 3 THR 0.064200 + 47 HG23 4.1140 6.0370 -0.1590 HC 3 THR 0.064200 + 48 OG1 1.9340 5.8350 1.2520 OH 3 THR -0.676100 + 49 HG1 1.0470 5.5790 0.9870 HO 3 THR 0.410200 + 50 C 0.1770 8.3480 0.5590 C 3 THR 0.597300 + 51 O -0.5460 7.7100 1.3220 O 3 THR -0.567900 + 52 N -0.2540 9.1390 -0.4260 N 4 TRP -0.415700 + 53 H 0.4680 9.3800 -1.0900 H 4 TRP 0.271900 + 54 CA -1.6150 9.5770 -0.6590 CT 4 TRP -0.027500 + 55 HA -2.0590 9.8610 0.2950 H1 4 TRP 0.112300 + 56 CB -1.5490 10.7590 -1.6220 CT 4 TRP -0.005000 + 57 HB2 -2.5230 11.2410 -1.7000 HC 4 TRP 0.033900 + 58 HB3 -1.2930 10.3820 -2.6120 HC 4 TRP 0.033900 + 59 CG -0.6170 11.8350 -1.1640 C* 4 TRP -0.141500 + 60 CD1 0.5100 12.2580 -1.7800 CW 4 TRP -0.163800 + 61 HD1 0.7900 11.8710 -2.7480 H4 4 TRP 0.206200 + 62 NE1 1.1390 13.2530 -1.0570 NA 4 TRP -0.341800 + 63 HE1 2.0870 13.5510 -1.2360 H 4 TRP 0.341200 + 64 CE2 0.3920 13.6100 0.0470 CN 4 TRP 0.138000 + 65 CZ2 0.5330 14.5590 1.0660 CA 4 TRP -0.260100 + 66 HZ2 1.3660 15.2450 1.0200 HA 4 TRP 0.157200 + 67 CH2 -0.4930 14.6850 2.0100 CA 4 TRP -0.113400 + 68 HH2 -0.5290 15.4500 2.7730 HA 4 TRP 0.141700 + 69 CZ3 -1.6420 13.8920 1.9020 CA 4 TRP -0.197200 + 70 HZ3 -2.2450 13.9850 2.7930 HA 4 TRP 0.144700 + 71 CE3 -1.7580 12.9110 0.9110 CA 4 TRP -0.238700 + 72 HE3 -2.5760 12.2100 0.8330 HA 4 TRP 0.170000 + 73 CD2 -0.7600 12.7890 -0.0700 CB 4 TRP 0.124300 + 74 C -2.5100 8.4870 -1.2290 C 4 TRP 0.597300 + 75 O -3.6630 8.4600 -0.8030 O 4 TRP -0.567900 + 76 N -2.0780 7.6970 -2.2160 N 5 GLU -0.516300 + 77 H -1.0940 7.7230 -2.4400 H 5 GLU 0.293600 + 78 CA -2.7310 6.7540 -3.1010 CT 5 GLU 0.039700 + 79 HA -3.7800 7.0050 -3.2560 H1 5 GLU 0.110500 + 80 CB -2.2090 6.8360 -4.5320 CT 5 GLU 0.056000 + 81 HB2 -1.1450 6.6160 -4.4510 HC 5 GLU -0.017300 + 82 HB3 -2.3610 7.8800 -4.8080 HC 5 GLU -0.017300 + 83 CG -2.7940 6.0500 -5.7030 CT 5 GLU 0.013600 + 84 HG2 -2.6810 4.9800 -5.5290 HC 5 GLU -0.042500 + 85 HG3 -2.2160 6.3560 -6.5750 HC 5 GLU -0.042500 + 86 CD -4.2240 6.3440 -6.1330 C 5 GLU 0.805400 + 87 OE1 -4.4510 6.5460 -7.3450 O2 5 GLU -0.818800 + 88 OE2 -5.1000 6.4330 -5.2460 O2 5 GLU -0.818800 + 89 C -2.5550 5.3390 -2.5690 C 5 GLU 0.536600 + 90 O -1.4410 4.8390 -2.4270 O 5 GLU -0.581900 + 91 N -3.7040 4.6980 -2.3420 N 6 ASN -0.415700 + 92 H -4.6200 5.1160 -2.4220 H 6 ASN 0.271900 + 93 CA -3.8110 3.3420 -1.8420 CT 6 ASN 0.014300 + 94 HA -2.8510 3.1990 -1.3470 H1 6 ASN 0.104800 + 95 CB -4.8840 3.4250 -0.7610 CT 6 ASN -0.204100 + 96 HB2 -5.8730 3.5470 -1.2040 HC 6 ASN 0.079700 + 97 HB3 -4.8040 4.2290 -0.0290 HC 6 ASN 0.079700 + 98 CG -4.9140 2.2170 0.1650 C 6 ASN 0.713000 + 99 OD1 -4.0900 1.3100 0.2610 O 6 ASN -0.593100 + 100 ND2 -6.0380 1.9600 0.8360 N 6 ASN -0.919100 + 101 HD21 -6.8650 2.4570 0.5350 H 6 ASN 0.419600 + 102 HD22 -5.9860 1.1600 1.4500 H 6 ASN 0.419600 + 103 C -4.0910 2.3260 -2.9400 C 6 ASN 0.597300 + 104 O -4.9480 2.4370 -3.8130 O 6 ASN -0.567900 + 105 N -3.1570 1.4020 -3.1810 N 7 GLY -0.415700 + 106 H -2.4620 1.3100 -2.4540 H 7 GLY 0.271900 + 107 CA -3.1020 0.6060 -4.3900 CT 7 GLY -0.025200 + 108 HA2 -2.1310 0.8290 -4.8330 H1 7 GLY 0.069800 + 109 HA3 -3.6910 1.0980 -5.1650 H1 7 GLY 0.069800 + 110 C -3.4170 -0.8390 -4.0320 C 7 GLY 0.597300 + 111 O -4.4110 -1.0250 -3.3330 O 7 GLY -0.567900 + 112 N -2.5890 -1.7680 -4.5150 N 8 LYS -0.347900 + 113 H -1.7410 -1.4130 -4.9330 H 8 LYS 0.274700 + 114 CA -2.8350 -3.1850 -4.3410 CT 8 LYS -0.240000 + 115 HA -3.9220 -3.2580 -4.3570 H1 8 LYS 0.142600 + 116 CB -2.1980 -4.0480 -5.4270 CT 8 LYS -0.009400 + 117 HB2 -2.7430 -3.8290 -6.3450 HC 8 LYS 0.036200 + 118 HB3 -2.4080 -5.0360 -5.0180 HC 8 LYS 0.036200 + 119 CG -0.6890 -3.9440 -5.6290 CT 8 LYS 0.018700 + 120 HG2 -0.2550 -4.4970 -4.7960 HC 8 LYS 0.010300 + 121 HG3 -0.4260 -2.8950 -5.4990 HC 8 LYS 0.010300 + 122 CD -0.1980 -4.4550 -6.9810 CT 8 LYS -0.047900 + 123 HD2 0.8880 -4.4830 -6.8980 HC 8 LYS 0.062100 + 124 HD3 -0.4550 -3.7010 -7.7250 HC 8 LYS 0.062100 + 125 CE -0.6860 -5.8290 -7.4320 CT 8 LYS -0.014300 + 126 HE2 -1.7690 -5.8830 -7.3200 HP 8 LYS 0.113500 + 127 HE3 -0.1680 -6.5230 -6.7700 HP 8 LYS 0.113500 + 128 NZ -0.3370 -6.0660 -8.8410 N3 8 LYS -0.385400 + 129 HZ1 -0.7660 -5.3630 -9.4250 H 8 LYS 0.340000 + 130 HZ2 0.6400 -6.0670 -9.0940 H 8 LYS 0.340000 + 131 HZ3 -0.6800 -6.9550 -9.1770 H 8 LYS 0.340000 + 132 C -2.3160 -3.5830 -2.9670 C 8 LYS 0.734100 + 133 O -1.1040 -3.4790 -2.7890 O 8 LYS -0.589400 + 134 N -3.0860 -4.2590 -2.1110 N 9 TRP -0.415700 + 135 H -4.0420 -4.4080 -2.3980 H 9 TRP 0.271900 + 136 CA -2.6600 -4.7230 -0.8060 CT 9 TRP -0.027500 + 137 HA -1.7730 -4.1730 -0.4910 H1 9 TRP 0.112300 + 138 CB -3.7810 -4.5410 0.2130 CT 9 TRP -0.005000 + 139 HB2 -4.7080 -4.8780 -0.2510 HC 9 TRP 0.033900 + 140 HB3 -4.0050 -3.4960 0.4260 HC 9 TRP 0.033900 + 141 CG -3.7060 -5.3010 1.4980 C* 9 TRP -0.141500 + 142 CD1 -4.7770 -5.8720 2.0950 CW 9 TRP -0.163800 + 143 HD1 -5.7790 -5.8930 1.6930 H4 9 TRP 0.206200 + 144 NE1 -4.4220 -6.2750 3.3670 NA 9 TRP -0.341800 + 145 HE1 -5.0150 -6.7530 4.0300 H 9 TRP 0.341200 + 146 CE2 -3.1300 -5.8960 3.6700 CN 9 TRP 0.138000 + 147 CZ2 -2.4020 -5.9640 4.8640 CA 9 TRP -0.260100 + 148 HZ2 -2.6950 -6.5080 5.7500 HA 9 TRP 0.157200 + 149 CH2 -1.1630 -5.3180 4.9540 CA 9 TRP -0.113400 + 150 HH2 -0.6020 -5.5560 5.8460 HA 9 TRP 0.141700 + 151 CZ3 -0.6980 -4.6450 3.8190 CA 9 TRP -0.197200 + 152 HZ3 0.2340 -4.0990 3.8230 HA 9 TRP 0.144700 + 153 CE3 -1.3940 -4.6290 2.6040 CA 9 TRP -0.238700 + 154 HE3 -1.0030 -4.1390 1.7240 HA 9 TRP 0.170000 + 155 CD2 -2.6460 -5.2550 2.5000 CB 9 TRP 0.124300 + 156 C -2.2130 -6.1680 -0.9760 C 9 TRP 0.597300 + 157 O -3.0130 -7.0690 -1.2180 O 9 TRP -0.567900 + 158 N -0.8910 -6.3500 -0.9640 N 10 THR -0.415700 + 159 H -0.2710 -5.5620 -0.8410 H 10 THR 0.271900 + 160 CA -0.2810 -7.6350 -1.2400 CT 10 THR -0.038900 + 161 HA -1.0190 -8.3230 -1.6540 H1 10 THR 0.100700 + 162 CB 0.7780 -7.5450 -2.3350 CT 10 THR 0.365400 + 163 HB 1.6910 -7.2850 -1.7980 H1 10 THR 0.004300 + 164 CG2 1.1710 -8.9160 -2.8790 CT 10 THR -0.243800 + 165 HG21 0.2640 -9.5200 -2.8880 HC 10 THR 0.064200 + 166 HG22 1.6660 -8.7510 -3.8350 HC 10 THR 0.064200 + 167 HG23 1.8950 -9.3230 -2.1740 HC 10 THR 0.064200 + 168 OG1 0.3460 -6.6730 -3.3550 OH 10 THR -0.676100 + 169 HG1 -0.4820 -6.3160 -3.0260 HO 10 THR 0.410200 + 170 C 0.3190 -8.2680 0.0070 C 10 THR 0.597300 + 171 O 1.3670 -7.8130 0.4600 O 10 THR -0.567900 + 172 N -0.4430 -9.2260 0.5410 N 11 TRP -0.415700 + 173 H -1.2280 -9.5530 -0.0040 H 11 TRP 0.271900 + 174 CA 0.1090 -10.1190 1.5390 CT 11 TRP -0.027500 + 175 HA 0.6330 -9.4870 2.2560 H1 11 TRP 0.112300 + 176 CB -1.0830 -10.7510 2.2520 CT 11 TRP -0.005000 + 177 HB2 -1.6540 -11.4060 1.5950 HC 11 TRP 0.033900 + 178 HB3 -1.7080 -9.9570 2.6620 HC 11 TRP 0.033900 + 179 CG -0.8250 -11.5010 3.5190 C* 11 TRP -0.141500 + 180 CD1 -1.2060 -11.1470 4.7670 CW 11 TRP -0.163800 + 181 HD1 -1.7730 -10.2480 4.9580 H4 11 TRP 0.206200 + 182 NE1 -1.0310 -12.1720 5.6760 NA 11 TRP -0.341800 + 183 HE1 -1.3280 -12.0570 6.6350 H 11 TRP 0.341200 + 184 CE2 -0.5640 -13.2880 5.0120 CN 11 TRP 0.138000 + 185 CZ2 -0.3810 -14.5930 5.4850 CA 11 TRP -0.260100 + 186 HZ2 -0.7760 -14.8040 6.4680 HA 11 TRP 0.157200 + 187 CH2 -0.0320 -15.5760 4.5510 CA 11 TRP -0.113400 + 188 HH2 0.0740 -16.6110 4.8400 HA 11 TRP 0.141700 + 189 CZ3 0.2620 -15.1640 3.2460 CA 11 TRP -0.197200 + 190 HZ3 0.6650 -15.8180 2.4870 HA 11 TRP 0.144700 + 191 CE3 0.1060 -13.8530 2.7790 CA 11 TRP -0.238700 + 192 HE3 0.1380 -13.7790 1.7020 HA 11 TRP 0.170000 + 193 CD2 -0.3410 -12.8690 3.6750 CB 11 TRP 0.124300 + 194 C 0.9670 -11.2360 0.9620 C 11 TRP 0.597300 + 195 O 0.5120 -11.7740 -0.0450 O 11 TRP -0.567900 + 196 N 2.1830 -11.4910 1.4490 N 12 LYS -0.347900 + 197 H 2.3820 -10.9080 2.2500 H 12 LYS 0.274700 + 198 CA 3.2050 -12.2250 0.7310 CT 12 LYS -0.240000 + 199 HA 2.9190 -12.3340 -0.3150 H1 12 LYS 0.142600 + 200 CB 4.5960 -11.5960 0.7560 CT 12 LYS -0.009400 + 201 HB2 5.2880 -12.2530 0.2300 HC 12 LYS 0.036200 + 202 HB3 5.0080 -11.5380 1.7640 HC 12 LYS 0.036200 + 203 CG 4.5140 -10.2530 0.0360 CT 12 LYS 0.018700 + 204 HG2 3.9610 -9.6490 0.7550 HC 12 LYS 0.010300 + 205 HG3 4.0340 -10.2640 -0.9420 HC 12 LYS 0.010300 + 206 CD 5.9260 -9.7320 -0.2170 CT 12 LYS -0.047900 + 207 HD2 5.8450 -8.9600 -0.9830 HC 12 LYS 0.062100 + 208 HD3 6.5570 -10.5160 -0.6350 HC 12 LYS 0.062100 + 209 CE 6.4920 -9.1750 1.0860 CT 12 LYS -0.014300 + 210 HE2 6.5540 -9.9710 1.8280 HP 12 LYS 0.113500 + 211 HE3 5.9050 -8.3500 1.4890 HP 12 LYS 0.113500 + 212 NZ 7.8460 -8.6300 0.9030 N3 12 LYS -0.385400 + 213 HZ1 8.4290 -9.2390 0.3470 H 12 LYS 0.340000 + 214 HZ2 7.7160 -7.6670 0.6250 H 12 LYS 0.340000 + 215 HZ3 8.3240 -8.5610 1.7900 H 12 LYS 0.340000 + 216 C 3.3250 -13.6210 1.3240 C 12 LYS 0.734100 + 217 O 3.5350 -14.5920 0.6000 O 12 LYS -0.589400 + 218 N 3.3440 -13.7680 2.6510 N 13 NME -0.415700 + 219 H 3.1190 -13.0160 3.2860 H 13 NME 0.271900 + 220 CH3 3.8420 -14.9450 3.3330 CT 13 NME -0.149000 + 221 HH31 3.7040 -15.8420 2.7280 H1 13 NME 0.097600 + 222 HH32 4.9170 -14.8610 3.4950 H1 13 NME 0.097600 + 223 HH33 3.3230 -15.0060 4.2890 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N 0.3010 5.0950 3.4810 N3 1 SER 0.184900 + 2 H1 1.2180 5.1430 3.0600 H 1 SER 0.189800 + 3 H2 0.0670 4.1670 3.8040 H 1 SER 0.189800 + 4 H3 -0.3180 5.3210 2.7150 H 1 SER 0.189800 + 5 CA 0.2210 6.1460 4.5060 CT 1 SER 0.056700 + 6 HA -0.7310 6.0600 5.0290 HP 1 SER 0.078200 + 7 CB 1.2970 5.9460 5.5700 CT 1 SER 0.259600 + 8 HB2 1.1310 4.9640 6.0130 H1 1 SER 0.027300 + 9 HB3 1.1760 6.6720 6.3740 H1 1 SER 0.027300 + 10 OG 2.5560 5.8240 4.9460 OH 1 SER -0.671400 + 11 HG 3.2230 6.0380 5.6030 HO 1 SER 0.423900 + 12 C 0.2630 7.4890 3.7900 C 1 SER 0.616300 + 13 O -0.7520 7.9980 3.3210 O 1 SER -0.572200 + 14 N 1.4790 8.0150 3.6270 N 2 TRP -0.415700 + 15 H 2.2330 7.3980 3.8940 H 2 TRP 0.271900 + 16 CA 1.7000 9.2640 2.9270 CT 2 TRP -0.027500 + 17 HA 1.3780 10.0630 3.5950 H1 2 TRP 0.112300 + 18 CB 3.1920 9.3840 2.6310 CT 2 TRP -0.005000 + 19 HB2 3.4660 8.5520 1.9830 HC 2 TRP 0.033900 + 20 HB3 3.7710 9.2560 3.5460 HC 2 TRP 0.033900 + 21 CG 3.7140 10.6010 1.9370 C* 2 TRP -0.141500 + 22 CD1 3.5170 11.8800 2.3300 CW 2 TRP -0.163800 + 23 HD1 3.0130 12.1490 3.2460 H4 2 TRP 0.206200 + 24 NE1 4.1350 12.8130 1.5210 NA 2 TRP -0.341800 + 25 HE1 4.2370 13.8000 1.7070 H 2 TRP 0.341200 + 26 CE2 4.6740 12.1110 0.4620 CN 2 TRP 0.138000 + 27 CZ2 5.3000 12.5110 -0.7250 CA 2 TRP -0.260100 + 28 HZ2 5.3280 13.5800 -0.8730 HA 2 TRP 0.157200 + 29 CH2 5.8800 11.5530 -1.5650 CA 2 TRP -0.113400 + 30 HH2 6.3950 11.9660 -2.4190 HA 2 TRP 0.141700 + 31 CZ3 5.8000 10.1890 -1.2560 CA 2 TRP -0.197200 + 32 HZ3 6.2740 9.4740 -1.9130 HA 2 TRP 0.144700 + 33 CE3 5.0560 9.7740 -0.1460 CA 2 TRP -0.238700 + 34 HE3 5.1630 8.7320 0.1150 HA 2 TRP 0.170000 + 35 CD2 4.5710 10.7280 0.7630 CB 2 TRP 0.124300 + 36 C 0.8820 9.5030 1.6650 C 2 TRP 0.597300 + 37 O 0.2420 10.5280 1.4420 O 2 TRP -0.567900 + 38 N 0.7320 8.4520 0.8560 N 3 THR -0.415700 + 39 H 1.3680 7.6830 1.0140 H 3 THR 0.271900 + 40 CA 0.0200 8.4480 -0.4060 CT 3 THR -0.038900 + 41 HA -0.3590 9.4470 -0.6210 H1 3 THR 0.100700 + 42 CB 1.0290 8.1310 -1.5060 CT 3 THR 0.365400 + 43 HB 0.5640 7.7710 -2.4230 H1 3 THR 0.004300 + 44 CG2 1.9730 9.2140 -2.0210 CT 3 THR -0.243800 + 45 HG21 1.5560 9.8300 -2.8180 HC 3 THR 0.064200 + 46 HG22 2.2350 9.9330 -1.2450 HC 3 THR 0.064200 + 47 HG23 2.8890 8.9180 -2.5340 HC 3 THR 0.064200 + 48 OG1 1.8590 7.0550 -1.1290 OH 3 THR -0.676100 + 49 HG1 1.3170 6.2730 -1.2590 HO 3 THR 0.410200 + 50 C -1.1370 7.4600 -0.4090 C 3 THR 0.597300 + 51 O -0.9660 6.2450 -0.3330 O 3 THR -0.567900 + 52 N -2.2800 8.1510 -0.3870 N 4 TRP -0.415700 + 53 H -2.1080 9.1450 -0.3400 H 4 TRP 0.271900 + 54 CA -3.6590 7.7690 -0.1630 CT 4 TRP -0.027500 + 55 HA -3.8420 7.6810 0.9080 H1 4 TRP 0.112300 + 56 CB -4.5810 8.7740 -0.8470 CT 4 TRP -0.005000 + 57 HB2 -5.5910 8.3880 -0.7080 HC 4 TRP 0.033900 + 58 HB3 -4.4180 8.8490 -1.9220 HC 4 TRP 0.033900 + 59 CG -4.6410 10.1810 -0.3440 C* 4 TRP -0.141500 + 60 CD1 -4.7900 11.2240 -1.1910 CW 4 TRP -0.163800 + 61 HD1 -4.9030 11.0270 -2.2460 H4 4 TRP 0.206200 + 62 NE1 -4.6600 12.3900 -0.4610 NA 4 TRP -0.341800 + 63 HE1 -4.7500 13.2800 -0.9290 H 4 TRP 0.341200 + 64 CE2 -4.2900 12.1860 0.8530 CN 4 TRP 0.138000 + 65 CZ2 -3.9240 13.0710 1.8740 CA 4 TRP -0.260100 + 66 HZ2 -4.0050 14.1470 1.8540 HA 4 TRP 0.157200 + 67 CH2 -3.4650 12.4880 3.0610 CA 4 TRP -0.113400 + 68 HH2 -3.3610 13.1690 3.8930 HA 4 TRP 0.141700 + 69 CZ3 -3.3980 11.1010 3.2350 CA 4 TRP -0.197200 + 70 HZ3 -3.1020 10.7970 4.2290 HA 4 TRP 0.144700 + 71 CE3 -3.7100 10.2870 2.1390 CA 4 TRP -0.238700 + 72 HE3 -3.3970 9.2570 2.2170 HA 4 TRP 0.170000 + 73 CD2 -4.1850 10.7720 0.9100 CB 4 TRP 0.124300 + 74 C -3.9220 6.3750 -0.7160 C 4 TRP 0.597300 + 75 O -4.3510 5.4380 -0.0460 O 4 TRP -0.567900 + 76 N -3.5750 6.1970 -1.9930 N 5 GLU -0.516300 + 77 H -2.8040 6.7680 -2.3070 H 5 GLU 0.293600 + 78 CA -3.6850 4.8950 -2.6190 CT 5 GLU 0.039700 + 79 HA -4.7310 4.6020 -2.5240 H1 5 GLU 0.110500 + 80 CB -3.4540 4.9990 -4.1240 CT 5 GLU 0.056000 + 81 HB2 -2.4170 5.3160 -4.2420 HC 5 GLU -0.017300 + 82 HB3 -3.9110 5.9520 -4.3910 HC 5 GLU -0.017300 + 83 CG -3.8480 3.7820 -4.9560 CT 5 GLU 0.013600 + 84 HG2 -3.3720 2.9290 -4.4730 HC 5 GLU -0.042500 + 85 HG3 -3.4180 4.0230 -5.9280 HC 5 GLU -0.042500 + 86 CD -5.3630 3.6290 -4.9640 C 5 GLU 0.805400 + 87 OE1 -5.8800 2.7900 -4.1950 O2 5 GLU -0.818800 + 88 OE2 -6.0030 4.1590 -5.8970 O2 5 GLU -0.818800 + 89 C -2.8420 3.7170 -2.1540 C 5 GLU 0.536600 + 90 O -1.6150 3.7460 -2.0930 O 5 GLU -0.581900 + 91 N -3.5360 2.6160 -1.8550 N 6 ASN -0.415700 + 92 H -4.4930 2.5490 -2.1690 H 6 ASN 0.271900 + 93 CA -2.9350 1.3750 -1.4080 CT 6 ASN 0.014300 + 94 HA -2.1070 1.5610 -0.7250 H1 6 ASN 0.104800 + 95 CB -3.9840 0.5920 -0.6240 CT 6 ASN -0.204100 + 96 HB2 -3.7660 -0.4620 -0.4480 HC 6 ASN 0.079700 + 97 HB3 -4.9620 0.5560 -1.1040 HC 6 ASN 0.079700 + 98 CG -4.1980 1.1560 0.7730 C 6 ASN 0.713000 + 99 OD1 -3.3630 1.8770 1.3150 O 6 ASN -0.593100 + 100 ND2 -5.2480 0.7730 1.5020 N 6 ASN -0.919100 + 101 HD21 -5.9470 0.2150 1.0340 H 6 ASN 0.419600 + 102 HD22 -5.0680 0.5820 2.4770 H 6 ASN 0.419600 + 103 C -2.4080 0.6240 -2.6220 C 6 ASN 0.597300 + 104 O -3.0900 -0.0830 -3.3610 O 6 ASN -0.567900 + 105 N -1.1320 0.8740 -2.9240 N 7 GLY -0.415700 + 106 H -0.6340 1.4920 -2.2990 H 7 GLY 0.271900 + 107 CA -0.3700 0.3030 -4.0160 CT 7 GLY -0.025200 + 108 HA2 0.2760 1.1220 -4.3340 H1 7 GLY 0.069800 + 109 HA3 -0.8850 -0.1190 -4.8780 H1 7 GLY 0.069800 + 110 C 0.5420 -0.7730 -3.4440 C 7 GLY 0.597300 + 111 O 0.0270 -1.7090 -2.8370 O 7 GLY -0.567900 + 112 N 1.8310 -0.8120 -3.7900 N 8 LYS -0.347900 + 113 H 2.1010 -0.1600 -4.5120 H 8 LYS 0.274700 + 114 CA 2.7440 -1.8720 -3.4130 CT 8 LYS -0.240000 + 115 HA 2.3210 -2.7490 -3.9030 H1 8 LYS 0.142600 + 116 CB 4.1160 -1.6950 -4.0570 CT 8 LYS -0.009400 + 117 HB2 3.8900 -1.4230 -5.0880 HC 8 LYS 0.036200 + 118 HB3 4.6140 -2.6630 -4.1180 HC 8 LYS 0.036200 + 119 CG 4.9800 -0.6310 -3.3850 CT 8 LYS 0.018700 + 120 HG2 5.3600 -1.0670 -2.4610 HC 8 LYS 0.010300 + 121 HG3 4.4910 0.2870 -3.0610 HC 8 LYS 0.010300 + 122 CD 6.2420 -0.3740 -4.2040 CT 8 LYS -0.047900 + 123 HD2 6.0220 -0.1470 -5.2470 HC 8 LYS 0.062100 + 124 HD3 6.9160 -1.2290 -4.1580 HC 8 LYS 0.062100 + 125 CE 6.9590 0.8480 -3.6380 CT 8 LYS -0.014300 + 126 HE2 7.9730 0.8560 -4.0370 HP 8 LYS 0.113500 + 127 HE3 6.8790 0.6440 -2.5710 HP 8 LYS 0.113500 + 128 NZ 6.2620 2.0980 -3.9790 N3 8 LYS -0.385400 + 129 HZ1 5.2850 2.0500 -3.7280 H 8 LYS 0.340000 + 130 HZ2 6.7530 2.8470 -3.5130 H 8 LYS 0.340000 + 131 HZ3 6.4380 2.3400 -4.9440 H 8 LYS 0.340000 + 132 C 2.8310 -2.2170 -1.9330 C 8 LYS 0.734100 + 133 O 3.0640 -1.3380 -1.1060 O 8 LYS -0.589400 + 134 N 2.6180 -3.4740 -1.5370 N 9 TRP -0.415700 + 135 H 2.1440 -4.1290 -2.1420 H 9 TRP 0.271900 + 136 CA 2.6630 -3.8540 -0.1400 CT 9 TRP -0.027500 + 137 HA 3.6010 -3.5120 0.2970 H1 9 TRP 0.112300 + 138 CB 1.5140 -3.2140 0.6340 CT 9 TRP -0.005000 + 139 HB2 0.6280 -3.5700 0.1100 HC 9 TRP 0.033900 + 140 HB3 1.5820 -2.1270 0.5800 HC 9 TRP 0.033900 + 141 CG 1.2990 -3.5090 2.0840 C* 9 TRP -0.141500 + 142 CD1 0.3530 -4.4020 2.4550 CW 9 TRP -0.163800 + 143 HD1 -0.0850 -5.1530 1.8150 H4 9 TRP 0.206200 + 144 NE1 0.3820 -4.4840 3.8330 NA 9 TRP -0.341800 + 145 HE1 -0.2960 -5.0450 4.3290 H 9 TRP 0.341200 + 146 CE2 1.0510 -3.3930 4.3500 CN 9 TRP 0.138000 + 147 CZ2 1.1900 -2.7800 5.6010 CA 9 TRP -0.260100 + 148 HZ2 0.4740 -2.9170 6.3980 HA 9 TRP 0.157200 + 149 CH2 1.9850 -1.6440 5.7910 CA 9 TRP -0.113400 + 150 HH2 1.8620 -1.1090 6.7210 HA 9 TRP 0.141700 + 151 CZ3 2.6350 -1.0090 4.7250 CA 9 TRP -0.197200 + 152 HZ3 3.1800 -0.0920 4.8920 HA 9 TRP 0.144700 + 153 CE3 2.5580 -1.6800 3.4990 CA 9 TRP -0.238700 + 154 HE3 3.0630 -1.1330 2.7170 HA 9 TRP 0.170000 + 155 CD2 1.8060 -2.8460 3.2800 CB 9 TRP 0.124300 + 156 C 2.5500 -5.3710 -0.0830 C 9 TRP 0.597300 + 157 O 2.1130 -6.0440 -1.0130 O 9 TRP -0.567900 + 158 N 3.1450 -6.0520 0.8990 N 10 THR -0.415700 + 159 H 3.7160 -5.4550 1.4800 H 10 THR 0.271900 + 160 CA 3.3500 -7.4360 1.2750 CT 10 THR -0.038900 + 161 HA 4.0830 -7.8170 0.5630 H1 10 THR 0.100700 + 162 CB 4.0800 -7.4820 2.6140 CT 10 THR 0.365400 + 163 HB 3.3590 -7.1710 3.3700 H1 10 THR 0.004300 + 164 CG2 4.3910 -8.9190 3.0210 CT 10 THR -0.243800 + 165 HG21 4.6860 -8.9400 4.0710 HC 10 THR 0.064200 + 166 HG22 3.5050 -9.5430 2.9110 HC 10 THR 0.064200 + 167 HG23 5.1550 -9.3980 2.4080 HC 10 THR 0.064200 + 168 OG1 5.2360 -6.6740 2.6210 OH 10 THR -0.676100 + 169 HG1 5.6790 -6.7800 3.4660 HO 10 THR 0.410200 + 170 C 2.0470 -8.2220 1.3080 C 10 THR 0.597300 + 171 O 1.1790 -7.8690 2.1040 O 10 THR -0.567900 + 172 N 1.8690 -9.2730 0.5040 N 11 TRP -0.415700 + 173 H 2.5980 -9.4140 -0.1810 H 11 TRP 0.271900 + 174 CA 0.5790 -9.9020 0.3050 CT 11 TRP -0.027500 + 175 HA -0.0680 -9.0310 0.2070 H1 11 TRP 0.112300 + 176 CB 0.5250 -10.7550 -0.9590 CT 11 TRP -0.005000 + 177 HB2 1.3450 -11.4710 -0.9060 HC 11 TRP 0.033900 + 178 HB3 0.8910 -10.1720 -1.8040 HC 11 TRP 0.033900 + 179 CG -0.7310 -11.4760 -1.3310 C* 11 TRP -0.141500 + 180 CD1 -2.0030 -11.0340 -1.2130 CW 11 TRP -0.163800 + 181 HD1 -2.2680 -10.0390 -0.8880 H4 11 TRP 0.206200 + 182 NE1 -2.9000 -11.9980 -1.6290 NA 11 TRP -0.341800 + 183 HE1 -3.8560 -11.9080 -1.3150 H 11 TRP 0.341200 + 184 CE2 -2.2570 -13.1100 -2.1340 CN 11 TRP 0.138000 + 185 CZ2 -2.7240 -14.3130 -2.6770 CA 11 TRP -0.260100 + 186 HZ2 -3.7840 -14.4650 -2.8230 HA 11 TRP 0.157200 + 187 CH2 -1.7810 -15.3080 -2.9570 CA 11 TRP -0.113400 + 188 HH2 -2.0750 -16.2560 -3.3830 HA 11 TRP 0.141700 + 189 CZ3 -0.4200 -14.9860 -2.8930 CA 11 TRP -0.197200 + 190 HZ3 0.3180 -15.6940 -3.2400 HA 11 TRP 0.144700 + 191 CE3 0.0260 -13.7470 -2.4160 CA 11 TRP -0.238700 + 192 HE3 1.0330 -13.3590 -2.3800 HA 11 TRP 0.170000 + 193 CD2 -0.8870 -12.7850 -1.9560 CB 11 TRP 0.124300 + 194 C 0.1090 -10.6420 1.5490 C 11 TRP 0.597300 + 195 O 0.9370 -11.3200 2.1540 O 11 TRP -0.567900 + 196 N -1.1490 -10.5430 1.9840 N 12 LYS -0.347900 + 197 H -1.8010 -9.8950 1.5660 H 12 LYS 0.274700 + 198 CA -1.7380 -11.2680 3.0920 CT 12 LYS -0.240000 + 199 HA -1.1760 -11.1530 4.0190 H1 12 LYS 0.142600 + 200 CB -3.1720 -10.8270 3.3690 CT 12 LYS -0.009400 + 201 HB2 -3.8140 -11.7040 3.2860 HC 12 LYS 0.036200 + 202 HB3 -3.4450 -10.2270 2.5010 HC 12 LYS 0.036200 + 203 CG -3.3030 -10.1340 4.7220 CT 12 LYS 0.018700 + 204 HG2 -2.4810 -9.4490 4.9280 HC 12 LYS 0.010300 + 205 HG3 -3.3990 -10.9100 5.4820 HC 12 LYS 0.010300 + 206 CD -4.5850 -9.3070 4.7600 CT 12 LYS -0.047900 + 207 HD2 -5.4120 -9.9830 4.5440 HC 12 LYS 0.062100 + 208 HD3 -4.6440 -8.5470 3.9800 HC 12 LYS 0.062100 + 209 CE -4.9060 -8.6240 6.0860 CT 12 LYS -0.014300 + 210 HE2 -4.4680 -7.6350 5.9510 HP 12 LYS 0.113500 + 211 HE3 -4.3690 -9.1200 6.8950 HP 12 LYS 0.113500 + 212 NZ -6.3350 -8.4060 6.3560 N3 12 LYS -0.385400 + 213 HZ1 -6.9020 -7.8970 5.6930 H 12 LYS 0.340000 + 214 HZ2 -6.7830 -9.3110 6.3790 H 12 LYS 0.340000 + 215 HZ3 -6.4710 -7.9030 7.2210 H 12 LYS 0.340000 + 216 C -1.6970 -12.7680 2.8330 C 12 LYS 0.734100 + 217 O -1.2120 -13.5820 3.6160 O 12 LYS -0.589400 + 218 N -2.0990 -13.2000 1.6360 N 13 NME -0.415700 + 219 H -2.4040 -12.5770 0.9020 H 13 NME 0.271900 + 220 CH3 -2.0740 -14.5120 1.0220 CT 13 NME -0.149000 + 221 HH31 -2.0220 -14.4480 -0.0650 H1 13 NME 0.097600 + 222 HH32 -1.2460 -15.0640 1.4670 H1 13 NME 0.097600 + 223 HH33 -3.0180 -15.0540 1.0830 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -4.9870 12.1270 0.2260 N3 1 SER 0.184900 + 2 H1 -5.0750 13.0270 0.6760 H 1 SER 0.189800 + 3 H2 -4.3620 12.3890 -0.5220 H 1 SER 0.189800 + 4 H3 -5.8880 12.0290 -0.2200 H 1 SER 0.189800 + 5 CA -4.4890 10.9200 0.9030 CT 1 SER 0.056700 + 6 HA -5.3200 10.6990 1.5720 HP 1 SER 0.078200 + 7 CB -4.3050 9.7040 0.0000 CT 1 SER 0.259600 + 8 HB2 -3.4420 9.8550 -0.6500 H1 1 SER 0.027300 + 9 HB3 -5.2580 9.8090 -0.5190 H1 1 SER 0.027300 + 10 OG -4.4590 8.4670 0.6600 OH 1 SER -0.671400 + 11 HG -4.3210 7.8490 -0.0620 HO 1 SER 0.423900 + 12 C -3.1950 11.1690 1.6640 C 1 SER 0.616300 + 13 O -2.5400 12.1880 1.4560 O 1 SER -0.572200 + 14 N -2.7790 10.1710 2.4470 N 2 TRP -0.415700 + 15 H -3.3620 9.3510 2.5310 H 2 TRP 0.271900 + 16 CA -1.4720 10.0320 3.0570 CT 2 TRP -0.027500 + 17 HA -0.9990 10.9660 3.3610 H1 2 TRP 0.112300 + 18 CB -1.5020 9.2190 4.3480 CT 2 TRP -0.005000 + 19 HB2 -2.0920 8.3470 4.0650 HC 2 TRP 0.033900 + 20 HB3 -2.1690 9.6760 5.0790 HC 2 TRP 0.033900 + 21 CG -0.2000 8.7670 4.9270 C* 2 TRP -0.141500 + 22 CD1 0.8140 9.5430 5.3730 CW 2 TRP -0.163800 + 23 HD1 0.8930 10.6180 5.3120 H4 2 TRP 0.206200 + 24 NE1 1.8820 8.7820 5.8060 NA 2 TRP -0.341800 + 25 HE1 2.7250 9.1500 6.2220 H 2 TRP 0.341200 + 26 CE2 1.6160 7.4330 5.6850 CN 2 TRP 0.138000 + 27 CZ2 2.3410 6.2680 5.9610 CA 2 TRP -0.260100 + 28 HZ2 3.3530 6.4200 6.3060 HA 2 TRP 0.157200 + 29 CH2 1.7520 5.0010 5.8800 CA 2 TRP -0.113400 + 30 HH2 2.2080 4.0610 6.1570 HA 2 TRP 0.141700 + 31 CZ3 0.4350 5.0060 5.4070 CA 2 TRP -0.197200 + 32 HZ3 -0.1120 4.0800 5.3110 HA 2 TRP 0.144700 + 33 CE3 -0.3210 6.1520 5.1290 CA 2 TRP -0.238700 + 34 HE3 -1.3750 6.0750 4.9070 HA 2 TRP 0.170000 + 35 CD2 0.2730 7.4200 5.2260 CB 2 TRP 0.124300 + 36 C -0.4280 9.5710 2.0490 C 2 TRP 0.597300 + 37 O 0.5620 10.2830 1.9010 O 2 TRP -0.567900 + 38 N -0.8730 8.5380 1.3300 N 3 THR -0.415700 + 39 H -1.6650 8.0590 1.7340 H 3 THR 0.271900 + 40 CA -0.0550 8.0770 0.2270 CT 3 THR -0.038900 + 41 HA 0.8220 8.7180 0.1400 H1 3 THR 0.100700 + 42 CB 0.4370 6.6510 0.4620 CT 3 THR 0.365400 + 43 HB 0.9760 6.3950 -0.4500 H1 3 THR 0.004300 + 44 CG2 1.3370 6.5430 1.6890 CT 3 THR -0.243800 + 45 HG21 0.7660 6.8220 2.5740 HC 3 THR 0.064200 + 46 HG22 1.8040 5.5630 1.7930 HC 3 THR 0.064200 + 47 HG23 2.1050 7.3070 1.5720 HC 3 THR 0.064200 + 48 OG1 -0.5060 5.6150 0.6180 OH 3 THR -0.676100 + 49 HG1 -0.0680 4.8150 0.9180 HO 3 THR 0.410200 + 50 C -0.6770 8.2700 -1.1490 C 3 THR 0.597300 + 51 O -1.7230 7.7350 -1.5090 O 3 THR -0.567900 + 52 N 0.0090 9.0050 -2.0270 N 4 TRP -0.415700 + 53 H 0.9280 9.2880 -1.7190 H 4 TRP 0.271900 + 54 CA -0.1120 9.1710 -3.4610 CT 4 TRP -0.027500 + 55 HA -1.1570 9.2920 -3.7450 H1 4 TRP 0.112300 + 56 CB 0.6680 10.3960 -3.9310 CT 4 TRP -0.005000 + 57 HB2 0.6710 10.3010 -5.0170 HC 4 TRP 0.033900 + 58 HB3 1.7150 10.3070 -3.6410 HC 4 TRP 0.033900 + 59 CG 0.1930 11.6880 -3.3490 C* 4 TRP -0.141500 + 60 CD1 -0.8320 12.4470 -3.7990 CW 4 TRP -0.163800 + 61 HD1 -1.3880 12.1760 -4.6850 H4 4 TRP 0.206200 + 62 NE1 -0.9700 13.5530 -2.9840 NA 4 TRP -0.341800 + 63 HE1 -1.5040 14.3920 -3.1590 H 4 TRP 0.341200 + 64 CE2 0.0290 13.6050 -2.0330 CN 4 TRP 0.138000 + 65 CZ2 0.3690 14.5660 -1.0730 CA 4 TRP -0.260100 + 66 HZ2 -0.2640 15.4030 -0.8190 HA 4 TRP 0.157200 + 67 CH2 1.4480 14.3040 -0.2200 CA 4 TRP -0.113400 + 68 HH2 1.7510 14.9780 0.5670 HA 4 TRP 0.141700 + 69 CZ3 2.1560 13.1050 -0.3650 CA 4 TRP -0.197200 + 70 HZ3 3.0430 12.8780 0.2080 HA 4 TRP 0.144700 + 71 CE3 1.8630 12.1750 -1.3710 CA 4 TRP -0.238700 + 72 HE3 2.4380 11.2620 -1.3600 HA 4 TRP 0.170000 + 73 CD2 0.7670 12.4080 -2.2170 CB 4 TRP 0.124300 + 74 C 0.2450 7.9620 -4.3140 C 4 TRP 0.597300 + 75 O -0.5330 7.4720 -5.1290 O 4 TRP -0.567900 + 76 N 1.4790 7.4610 -4.2160 N 5 GLU -0.516300 + 77 H 2.1530 7.9870 -3.6780 H 5 GLU 0.293600 + 78 CA 1.7590 6.0760 -4.5360 CT 5 GLU 0.039700 + 79 HA 1.5360 5.9570 -5.5960 H1 5 GLU 0.110500 + 80 CB 3.2590 5.8270 -4.4000 CT 5 GLU 0.056000 + 81 HB2 3.4110 4.7520 -4.4930 HC 5 GLU -0.017300 + 82 HB3 3.5470 6.1960 -3.4160 HC 5 GLU -0.017300 + 83 CG 4.1910 6.4440 -5.4390 CT 5 GLU 0.013600 + 84 HG2 3.6650 6.2790 -6.3790 HC 5 GLU -0.042500 + 85 HG3 5.0370 5.7570 -5.4760 HC 5 GLU -0.042500 + 86 CD 4.4820 7.8700 -4.9930 C 5 GLU 0.805400 + 87 OE1 4.9180 8.1250 -3.8500 O2 5 GLU -0.818800 + 88 OE2 4.1860 8.7660 -5.8130 O2 5 GLU -0.818800 + 89 C 0.9170 5.1950 -3.6240 C 5 GLU 0.536600 + 90 O 1.0550 5.2150 -2.4030 O 5 GLU -0.581900 + 91 N 0.0650 4.3710 -4.2380 N 6 ASN -0.415700 + 92 H 0.2270 4.2920 -5.2320 H 6 ASN 0.271900 + 93 CA -0.9000 3.5590 -3.5250 CT 6 ASN 0.014300 + 94 HA -1.0240 3.9840 -2.5290 H1 6 ASN 0.104800 + 95 CB -2.1890 3.5290 -4.3420 CT 6 ASN -0.204100 + 96 HB2 -1.9810 3.0280 -5.2870 HC 6 ASN 0.079700 + 97 HB3 -2.6240 4.5230 -4.4470 HC 6 ASN 0.079700 + 98 CG -3.2770 2.6680 -3.7150 C 6 ASN 0.713000 + 99 OD1 -4.0370 3.0560 -2.8310 O 6 ASN -0.593100 + 100 ND2 -3.6590 1.5080 -4.2530 N 6 ASN -0.919100 + 101 HD21 -3.2670 1.1800 -5.1240 H 6 ASN 0.419600 + 102 HD22 -4.4660 1.0760 -3.8240 H 6 ASN 0.419600 + 103 C -0.1950 2.2400 -3.2430 C 6 ASN 0.597300 + 104 O 0.4770 1.7630 -4.1550 O 6 ASN -0.567900 + 105 N -0.3650 1.6010 -2.0830 N 7 GLY -0.415700 + 106 H -1.1250 1.9290 -1.5030 H 7 GLY 0.271900 + 107 CA 0.2320 0.3240 -1.7490 CT 7 GLY -0.025200 + 108 HA2 1.2990 0.3390 -1.9730 H1 7 GLY 0.069800 + 109 HA3 -0.2380 -0.4460 -2.3600 H1 7 GLY 0.069800 + 110 C 0.0960 0.0960 -0.2500 C 7 GLY 0.597300 + 111 O 0.8600 0.6080 0.5650 O 7 GLY -0.567900 + 112 N -1.0300 -0.5520 0.0550 N 8 LYS -0.347900 + 113 H -1.6010 -0.9060 -0.7000 H 8 LYS 0.274700 + 114 CA -1.3520 -0.9530 1.4100 CT 8 LYS -0.240000 + 115 HA -0.8190 -0.4670 2.2260 H1 8 LYS 0.142600 + 116 CB -2.8370 -0.7040 1.6580 CT 8 LYS -0.009400 + 117 HB2 -3.1690 -1.2170 2.5610 HC 8 LYS 0.036200 + 118 HB3 -3.4300 -0.9960 0.7910 HC 8 LYS 0.036200 + 119 CG -3.1880 0.7660 1.8630 CT 8 LYS 0.018700 + 120 HG2 -2.8720 1.2560 0.9420 HC 8 LYS 0.010300 + 121 HG3 -2.7030 1.0540 2.7960 HC 8 LYS 0.010300 + 122 CD -4.6750 1.0720 2.0160 CT 8 LYS -0.047900 + 123 HD2 -5.1270 0.6500 2.9140 HC 8 LYS 0.062100 + 124 HD3 -5.1700 0.4890 1.2390 HC 8 LYS 0.062100 + 125 CE -5.1750 2.5130 2.0430 CT 8 LYS -0.014300 + 126 HE2 -6.2610 2.5170 2.1290 HP 8 LYS 0.113500 + 127 HE3 -4.9620 2.9550 1.0690 HP 8 LYS 0.113500 + 128 NZ -4.4520 3.3420 3.0210 N3 8 LYS -0.385400 + 129 HZ1 -4.4810 2.9920 3.9680 H 8 LYS 0.340000 + 130 HZ2 -3.4870 3.4700 2.7530 H 8 LYS 0.340000 + 131 HZ3 -4.6560 4.3170 3.1840 H 8 LYS 0.340000 + 132 C -1.0580 -2.4440 1.4970 C 8 LYS 0.734100 + 133 O -1.6160 -3.1630 0.6710 O 8 LYS -0.589400 + 134 N -0.1330 -2.8730 2.3590 N 9 TRP -0.415700 + 135 H 0.2060 -2.1620 2.9920 H 9 TRP 0.271900 + 136 CA 0.3570 -4.2270 2.5170 CT 9 TRP -0.027500 + 137 HA 0.9450 -4.4780 1.6340 H1 9 TRP 0.112300 + 138 CB 1.2990 -4.2440 3.7170 CT 9 TRP -0.005000 + 139 HB2 0.8170 -4.0570 4.6760 HC 9 TRP 0.033900 + 140 HB3 2.0550 -3.4660 3.6100 HC 9 TRP 0.033900 + 141 CG 1.9770 -5.5710 3.8430 C* 9 TRP -0.141500 + 142 CD1 1.4200 -6.6180 4.4920 CW 9 TRP -0.163800 + 143 HD1 0.4630 -6.6900 4.9870 H4 9 TRP 0.206200 + 144 NE1 2.2770 -7.7000 4.4510 NA 9 TRP -0.341800 + 145 HE1 2.0180 -8.6090 4.8090 H 9 TRP 0.341200 + 146 CE2 3.3850 -7.4210 3.6770 CN 9 TRP 0.138000 + 147 CZ2 4.4810 -8.1780 3.2460 CA 9 TRP -0.260100 + 148 HZ2 4.5150 -9.2450 3.4130 HA 9 TRP 0.157200 + 149 CH2 5.4640 -7.5730 2.4550 CA 9 TRP -0.113400 + 150 HH2 6.3380 -8.1670 2.2290 HA 9 TRP 0.141700 + 151 CZ3 5.4440 -6.1860 2.2630 CA 9 TRP -0.197200 + 152 HZ3 6.2660 -5.6910 1.7680 HA 9 TRP 0.144700 + 153 CE3 4.2980 -5.4570 2.6030 CA 9 TRP -0.238700 + 154 HE3 4.3020 -4.3870 2.4570 HA 9 TRP 0.170000 + 155 CD2 3.2380 -6.0610 3.2980 CB 9 TRP 0.124300 + 156 C -0.7020 -5.3200 2.5520 C 9 TRP 0.597300 + 157 O -1.3680 -5.6530 3.5290 O 9 TRP -0.567900 + 158 N -0.8290 -6.0130 1.4180 N 10 THR -0.415700 + 159 H -0.2100 -5.7380 0.6690 H 10 THR 0.271900 + 160 CA -1.7360 -7.1250 1.2150 CT 10 THR -0.038900 + 161 HA -2.1050 -7.4760 2.1780 H1 10 THR 0.100700 + 162 CB -2.8750 -6.7250 0.2810 CT 10 THR 0.365400 + 163 HB -3.3200 -7.6720 -0.0230 H1 10 THR 0.004300 + 164 CG2 -3.9240 -5.9160 1.0370 CT 10 THR -0.243800 + 165 HG21 -3.5190 -4.9100 1.1510 HC 10 THR 0.064200 + 166 HG22 -4.7700 -5.7440 0.3710 HC 10 THR 0.064200 + 167 HG23 -4.3800 -6.4030 1.8990 HC 10 THR 0.064200 + 168 OG1 -2.4300 -5.9910 -0.8380 OH 10 THR -0.676100 + 169 HG1 -2.1010 -5.1350 -0.5550 HO 10 THR 0.410200 + 170 C -0.8920 -8.3140 0.7810 C 10 THR 0.597300 + 171 O -0.6040 -8.4730 -0.4040 O 10 THR -0.567900 + 172 N -0.6160 -9.2980 1.6400 N 11 TRP -0.415700 + 173 H -1.2400 -9.3830 2.4290 H 11 TRP 0.271900 + 174 CA 0.1410 -10.5070 1.3890 CT 11 TRP -0.027500 + 175 HA 0.5780 -10.5300 0.3910 H1 11 TRP 0.112300 + 176 CB 1.2810 -10.6520 2.3930 CT 11 TRP -0.005000 + 177 HB2 0.8030 -10.7920 3.3630 HC 11 TRP 0.033900 + 178 HB3 1.9020 -9.7620 2.4880 HC 11 TRP 0.033900 + 179 CG 2.3120 -11.6780 2.0470 C* 11 TRP -0.141500 + 180 CD1 3.2610 -11.5340 1.0950 CW 11 TRP -0.163800 + 181 HD1 3.2840 -10.7140 0.3920 H4 11 TRP 0.206200 + 182 NE1 3.9780 -12.7130 1.0440 NA 11 TRP -0.341800 + 183 HE1 4.8340 -12.8230 0.5180 H 11 TRP 0.341200 + 184 CE2 3.5060 -13.6530 1.9380 CN 11 TRP 0.138000 + 185 CZ2 3.9070 -14.9550 2.2610 CA 11 TRP -0.260100 + 186 HZ2 4.7300 -15.3450 1.6810 HA 11 TRP 0.157200 + 187 CH2 3.2550 -15.5920 3.3230 CA 11 TRP -0.113400 + 188 HH2 3.6470 -16.4830 3.7920 HA 11 TRP 0.141700 + 189 CZ3 2.1130 -15.0300 3.9050 CA 11 TRP -0.197200 + 190 HZ3 1.5440 -15.5980 4.6270 HA 11 TRP 0.144700 + 191 CE3 1.7480 -13.7080 3.6220 CA 11 TRP -0.238700 + 192 HE3 0.8580 -13.2280 4.0000 HA 11 TRP 0.170000 + 193 CD2 2.4030 -13.0330 2.5800 CB 11 TRP 0.124300 + 194 C -0.8080 -11.6930 1.2940 C 11 TRP 0.597300 + 195 O -1.4300 -12.0430 2.2940 O 11 TRP -0.567900 + 196 N -0.7620 -12.4030 0.1640 N 12 LYS -0.347900 + 197 H -0.0500 -12.1270 -0.4980 H 12 LYS 0.274700 + 198 CA -1.6020 -13.5400 -0.1550 CT 12 LYS -0.240000 + 199 HA -2.4910 -13.5140 0.4750 H1 12 LYS 0.142600 + 200 CB -2.0350 -13.3960 -1.6110 CT 12 LYS -0.009400 + 201 HB2 -2.4930 -14.3360 -1.9200 HC 12 LYS 0.036200 + 202 HB3 -1.1670 -13.4740 -2.2670 HC 12 LYS 0.036200 + 203 CG -2.9610 -12.2180 -1.8980 CT 12 LYS 0.018700 + 204 HG2 -2.3390 -11.3230 -1.8980 HC 12 LYS 0.010300 + 205 HG3 -3.7290 -12.2200 -1.1240 HC 12 LYS 0.010300 + 206 CD -3.5990 -12.2780 -3.2830 CT 12 LYS -0.047900 + 207 HD2 -4.0150 -13.2820 -3.3680 HC 12 LYS 0.062100 + 208 HD3 -2.7420 -12.2420 -3.9550 HC 12 LYS 0.062100 + 209 CE -4.6970 -11.2490 -3.5340 CT 12 LYS -0.014300 + 210 HE2 -4.2910 -10.2400 -3.6130 HP 12 LYS 0.113500 + 211 HE3 -5.3560 -11.3390 -2.6700 HP 12 LYS 0.113500 + 212 NZ -5.4090 -11.5270 -4.7900 N3 12 LYS -0.385400 + 213 HZ1 -6.3040 -11.0690 -4.8870 H 12 LYS 0.340000 + 214 HZ2 -4.9130 -11.1230 -5.5720 H 12 LYS 0.340000 + 215 HZ3 -5.6450 -12.4930 -4.9720 H 12 LYS 0.340000 + 216 C -1.0850 -14.8970 0.3020 C 12 LYS 0.734100 + 217 O -1.9360 -15.5620 0.8890 O 12 LYS -0.589400 + 218 N 0.1990 -15.2290 0.1540 N 13 NME -0.415700 + 219 H 0.7970 -14.5610 -0.3110 H 13 NME 0.271900 + 220 CH3 0.8400 -16.3400 0.8280 CT 13 NME -0.149000 + 221 HH31 1.5930 -16.8360 0.2160 H1 13 NME 0.097600 + 222 HH32 1.3330 -15.9500 1.7180 H1 13 NME 0.097600 + 223 HH33 0.0930 -17.0680 1.1470 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -0.7130 15.2770 1.6620 N3 1 SER 0.184900 + 2 H1 -0.3040 15.7290 2.4670 H 1 SER 0.189800 + 3 H2 -0.0420 15.2820 0.9070 H 1 SER 0.189800 + 4 H3 -1.5740 15.6650 1.3030 H 1 SER 0.189800 + 5 CA -1.0620 13.9380 2.1610 CT 1 SER 0.056700 + 6 HA -1.6780 13.9400 3.0600 HP 1 SER 0.078200 + 7 CB -1.7830 13.0880 1.1190 CT 1 SER 0.259600 + 8 HB2 -1.1010 12.6890 0.3680 H1 1 SER 0.027300 + 9 HB3 -2.5030 13.6500 0.5240 H1 1 SER 0.027300 + 10 OG -2.4130 11.9750 1.7110 OH 1 SER -0.671400 + 11 HG -3.3580 11.9850 1.5410 HO 1 SER 0.423900 + 12 C 0.1410 13.0910 2.5510 C 1 SER 0.616300 + 13 O 1.2490 13.3620 2.0930 O 1 SER -0.572200 + 14 N 0.0060 12.2030 3.5390 N 2 TRP -0.415700 + 15 H -0.9360 11.9610 3.8090 H 2 TRP 0.271900 + 16 CA 1.0360 11.3380 4.0770 CT 2 TRP -0.027500 + 17 HA 1.9950 11.8300 3.9110 H1 2 TRP 0.112300 + 18 CB 0.7480 11.1510 5.5630 CT 2 TRP -0.005000 + 19 HB2 -0.0780 10.4670 5.7590 HC 2 TRP 0.033900 + 20 HB3 0.3000 12.1110 5.8210 HC 2 TRP 0.033900 + 21 CG 1.8730 10.8870 6.5120 C* 2 TRP -0.141500 + 22 CD1 3.0070 10.1870 6.2820 CW 2 TRP -0.163800 + 23 HD1 3.3250 9.5830 5.4450 H4 2 TRP 0.206200 + 24 NE1 3.9120 10.2260 7.3250 NA 2 TRP -0.341800 + 25 HE1 4.9010 10.0510 7.2230 H 2 TRP 0.341200 + 26 CE2 3.3230 10.9010 8.3750 CN 2 TRP 0.138000 + 27 CZ2 3.7680 11.1970 9.6690 CA 2 TRP -0.260100 + 28 HZ2 4.7200 10.7460 9.9060 HA 2 TRP 0.157200 + 29 CH2 2.8880 11.9030 10.4990 CA 2 TRP -0.113400 + 30 HH2 3.1540 12.1010 11.5270 HA 2 TRP 0.141700 + 31 CZ3 1.6460 12.3520 10.0360 CA 2 TRP -0.197200 + 32 HZ3 1.0530 12.9020 10.7530 HA 2 TRP 0.144700 + 33 CE3 1.2290 12.0910 8.7250 CA 2 TRP -0.238700 + 34 HE3 0.2250 12.3690 8.4430 HA 2 TRP 0.170000 + 35 CD2 2.0730 11.3530 7.8800 CB 2 TRP 0.124300 + 36 C 1.2350 10.0340 3.3170 C 2 TRP 0.597300 + 37 O 2.3460 9.6120 3.0040 O 2 TRP -0.567900 + 38 N 0.1560 9.3130 3.0040 N 3 THR -0.415700 + 39 H -0.7710 9.6390 3.2390 H 3 THR 0.271900 + 40 CA 0.2840 8.0960 2.2280 CT 3 THR -0.038900 + 41 HA 1.2700 7.6860 2.4450 H1 3 THR 0.100700 + 42 CB -0.8310 7.1170 2.5840 CT 3 THR 0.365400 + 43 HB -0.7630 6.4180 1.7500 H1 3 THR 0.004300 + 44 CG2 -0.8100 6.4950 3.9770 CT 3 THR -0.243800 + 45 HG21 -1.2760 7.1430 4.7190 HC 3 THR 0.064200 + 46 HG22 -1.3710 5.5620 3.9360 HC 3 THR 0.064200 + 47 HG23 0.2210 6.2620 4.2440 HC 3 THR 0.064200 + 48 OG1 -2.0570 7.8130 2.5350 OH 3 THR -0.676100 + 49 HG1 -2.1750 8.0110 1.6040 HO 3 THR 0.410200 + 50 C 0.1740 8.3820 0.7370 C 3 THR 0.597300 + 51 O -0.7900 9.0600 0.3870 O 3 THR -0.567900 + 52 N 0.9720 7.8130 -0.1690 N 4 TRP -0.415700 + 53 H 1.7310 7.2170 0.1300 H 4 TRP 0.271900 + 54 CA 0.6140 7.9210 -1.5690 CT 4 TRP -0.027500 + 55 HA -0.0210 8.7950 -1.7120 H1 4 TRP 0.112300 + 56 CB 1.8760 8.2210 -2.3720 CT 4 TRP -0.005000 + 57 HB2 1.7670 7.9810 -3.4300 HC 4 TRP 0.033900 + 58 HB3 2.5660 7.4510 -2.0290 HC 4 TRP 0.033900 + 59 CG 2.3650 9.6330 -2.3120 C* 4 TRP -0.141500 + 60 CD1 1.6620 10.5860 -2.9660 CW 4 TRP -0.163800 + 61 HD1 0.7940 10.4220 -3.5880 H4 4 TRP 0.206200 + 62 NE1 2.2780 11.7790 -2.6440 NA 4 TRP -0.341800 + 63 HE1 1.9130 12.7070 -2.8030 H 4 TRP 0.341200 + 64 CE2 3.3000 11.6590 -1.7240 CN 4 TRP 0.138000 + 65 CZ2 4.1690 12.5570 -1.0920 CA 4 TRP -0.260100 + 66 HZ2 4.1850 13.6040 -1.3540 HA 4 TRP 0.157200 + 67 CH2 5.0300 12.0800 -0.0960 CA 4 TRP -0.113400 + 68 HH2 5.7320 12.6740 0.4700 HA 4 TRP 0.141700 + 69 CZ3 5.0110 10.7200 0.2350 CA 4 TRP -0.197200 + 70 HZ3 5.5980 10.3930 1.0810 HA 4 TRP 0.144700 + 71 CE3 4.1990 9.7950 -0.4310 CA 4 TRP -0.238700 + 72 HE3 4.2810 8.7310 -0.2620 HA 4 TRP 0.170000 + 73 CD2 3.3340 10.2720 -1.4290 CB 4 TRP 0.124300 + 74 C -0.1170 6.6560 -1.9960 C 4 TRP 0.597300 + 75 O -1.2130 6.7300 -2.5470 O 4 TRP -0.567900 + 76 N 0.5550 5.5090 -1.8690 N 5 GLU -0.516300 + 77 H 1.4450 5.5350 -1.3920 H 5 GLU 0.293600 + 78 CA 0.1100 4.2490 -2.4280 CT 5 GLU 0.039700 + 79 HA -0.1020 4.4910 -3.4690 H1 5 GLU 0.110500 + 80 CB 1.2890 3.2800 -2.4180 CT 5 GLU 0.056000 + 81 HB2 0.9290 2.2630 -2.5750 HC 5 GLU -0.017300 + 82 HB3 1.8120 3.2390 -1.4630 HC 5 GLU -0.017300 + 83 CG 2.2580 3.4340 -3.5870 CT 5 GLU 0.013600 + 84 HG2 1.7590 3.5120 -4.5530 HC 5 GLU -0.042500 + 85 HG3 2.8550 2.5460 -3.7940 HC 5 GLU -0.042500 + 86 CD 3.3670 4.4760 -3.5870 C 5 GLU 0.805400 + 87 OE1 3.8630 4.8220 -2.4930 O2 5 GLU -0.818800 + 88 OE2 3.8500 4.8670 -4.6720 O2 5 GLU -0.818800 + 89 C -1.1960 3.8290 -1.7680 C 5 GLU 0.536600 + 90 O -1.3620 3.6830 -0.5590 O 5 GLU -0.581900 + 91 N -2.2170 3.6270 -2.6050 N 6 ASN -0.415700 + 92 H -2.0380 3.9260 -3.5530 H 6 ASN 0.271900 + 93 CA -3.5350 3.1130 -2.2920 CT 6 ASN 0.014300 + 94 HA -3.6330 2.7110 -1.2830 H1 6 ASN 0.104800 + 95 CB -4.4710 4.3160 -2.3510 CT 6 ASN -0.204100 + 96 HB2 -4.3300 4.8280 -3.3030 HC 6 ASN 0.079700 + 97 HB3 -4.1070 5.0130 -1.5950 HC 6 ASN 0.079700 + 98 CG -5.9230 3.9390 -2.0990 C 6 ASN 0.713000 + 99 OD1 -6.2740 3.0170 -1.3650 O 6 ASN -0.593100 + 100 ND2 -6.9130 4.5880 -2.7160 N 6 ASN -0.919100 + 101 HD21 -6.7380 5.4590 -3.1970 H 6 ASN 0.419600 + 102 HD22 -7.8430 4.3540 -2.3970 H 6 ASN 0.419600 + 103 C -4.0130 2.0030 -3.2170 C 6 ASN 0.597300 + 104 O -4.2270 2.2180 -4.4080 O 6 ASN -0.567900 + 105 N -4.2180 0.8510 -2.5730 N 7 GLY -0.415700 + 106 H -4.0490 0.7590 -1.5820 H 7 GLY 0.271900 + 107 CA -4.8730 -0.2370 -3.2720 CT 7 GLY -0.025200 + 108 HA2 -4.7230 -0.1720 -4.3490 H1 7 GLY 0.069800 + 109 HA3 -5.9340 -0.0860 -3.0740 H1 7 GLY 0.069800 + 110 C -4.4080 -1.5620 -2.6850 C 7 GLY 0.597300 + 111 O -3.2440 -1.7130 -2.3220 O 7 GLY -0.567900 + 112 N -5.3920 -2.4240 -2.4190 N 8 LYS -0.347900 + 113 H -6.3440 -2.1220 -2.5680 H 8 LYS 0.274700 + 114 CA -5.2240 -3.6680 -1.6960 CT 8 LYS -0.240000 + 115 HA -4.9160 -3.5270 -0.6600 H1 8 LYS 0.142600 + 116 CB -6.5620 -4.3880 -1.5460 CT 8 LYS -0.009400 + 117 HB2 -6.3930 -5.3970 -1.1720 HC 8 LYS 0.036200 + 118 HB3 -7.0400 -4.5340 -2.5150 HC 8 LYS 0.036200 + 119 CG -7.6780 -3.6550 -0.8080 CT 8 LYS 0.018700 + 120 HG2 -7.9490 -2.8820 -1.5270 HC 8 LYS 0.010300 + 121 HG3 -7.3440 -3.2790 0.1590 HC 8 LYS 0.010300 + 122 CD -8.9090 -4.5030 -0.4990 CT 8 LYS -0.047900 + 123 HD2 -8.5850 -5.1030 0.3520 HC 8 LYS 0.062100 + 124 HD3 -9.1460 -5.0850 -1.3890 HC 8 LYS 0.062100 + 125 CE -10.1020 -3.6180 -0.1530 CT 8 LYS -0.014300 + 126 HE2 -10.8020 -3.4240 -0.9650 HP 8 LYS 0.113500 + 127 HE3 -9.6700 -2.6600 0.1370 HP 8 LYS 0.113500 + 128 NZ -10.7340 -4.1280 1.0740 N3 8 LYS -0.385400 + 129 HZ1 -11.4020 -4.8390 0.8120 H 8 LYS 0.340000 + 130 HZ2 -10.1030 -4.5320 1.7520 H 8 LYS 0.340000 + 131 HZ3 -11.3470 -3.4700 1.5320 H 8 LYS 0.340000 + 132 C -4.1230 -4.5170 -2.3160 C 8 LYS 0.734100 + 133 O -4.3360 -5.0200 -3.4170 O 8 LYS -0.589400 + 134 N -2.9850 -4.7150 -1.6480 N 9 TRP -0.415700 + 135 H -2.7840 -4.1360 -0.8450 H 9 TRP 0.271900 + 136 CA -1.8700 -5.5060 -2.1270 CT 9 TRP -0.027500 + 137 HA -1.8210 -5.2860 -3.1940 H1 9 TRP 0.112300 + 138 CB -0.5450 -5.0000 -1.5640 CT 9 TRP -0.005000 + 139 HB2 -0.4620 -5.1750 -0.4910 HC 9 TRP 0.033900 + 140 HB3 -0.5770 -3.9120 -1.6190 HC 9 TRP 0.033900 + 141 CG 0.6320 -5.6020 -2.2620 C* 9 TRP -0.141500 + 142 CD1 1.3570 -6.6230 -1.7530 CW 9 TRP -0.163800 + 143 HD1 1.0900 -7.0830 -0.8120 H4 9 TRP 0.206200 + 144 NE1 2.2700 -7.0050 -2.7150 NA 9 TRP -0.341800 + 145 HE1 2.8660 -7.8170 -2.6400 H 9 TRP 0.341200 + 146 CE2 2.3250 -6.1460 -3.7940 CN 9 TRP 0.138000 + 147 CZ2 3.1220 -6.0920 -4.9440 CA 9 TRP -0.260100 + 148 HZ2 3.8870 -6.8430 -5.0770 HA 9 TRP 0.157200 + 149 CH2 2.7880 -5.1100 -5.8840 CA 9 TRP -0.113400 + 150 HH2 3.4810 -4.9790 -6.7020 HA 9 TRP 0.141700 + 151 CZ3 1.7010 -4.2420 -5.7290 CA 9 TRP -0.197200 + 152 HZ3 1.4380 -3.5130 -6.4820 HA 9 TRP 0.144700 + 153 CE3 0.9100 -4.3780 -4.5820 CA 9 TRP -0.238700 + 154 HE3 0.1310 -3.6330 -4.5160 HA 9 TRP 0.170000 + 155 CD2 1.1890 -5.3220 -3.5810 CB 9 TRP 0.124300 + 156 C -1.9970 -6.9900 -1.8100 C 9 TRP 0.597300 + 157 O -2.3840 -7.3020 -0.6860 O 9 TRP -0.567900 + 158 N -1.6050 -7.8550 -2.7480 N 10 THR -0.415700 + 159 H -1.3240 -7.4720 -3.6390 H 10 THR 0.271900 + 160 CA -1.5120 -9.2860 -2.5370 CT 10 THR -0.038900 + 161 HA -2.3740 -9.7970 -2.1090 H1 10 THR 0.100700 + 162 CB -1.3460 -9.9210 -3.9150 CT 10 THR 0.365400 + 163 HB -1.3230 -10.9980 -3.7490 H1 10 THR 0.004300 + 164 CG2 -2.5910 -9.7150 -4.7730 CT 10 THR -0.243800 + 165 HG21 -2.7620 -8.6510 -4.9310 HC 10 THR 0.064200 + 166 HG22 -2.4430 -10.1490 -5.7620 HC 10 THR 0.064200 + 167 HG23 -3.5090 -10.1900 -4.4270 HC 10 THR 0.064200 + 168 OG1 -0.2790 -9.4410 -4.7010 OH 10 THR -0.676100 + 169 HG1 0.4200 -9.3190 -4.0550 HO 10 THR 0.410200 + 170 C -0.4270 -9.5610 -1.5060 C 10 THR 0.597300 + 171 O 0.6770 -9.8430 -1.9660 O 10 THR -0.567900 + 172 N -0.6450 -9.6460 -0.1910 N 11 TRP -0.415700 + 173 H -1.5150 -9.2960 0.1840 H 11 TRP 0.271900 + 174 CA 0.3450 -9.8350 0.8500 CT 11 TRP -0.027500 + 175 HA 1.3570 -9.6090 0.5140 H1 11 TRP 0.112300 + 176 CB -0.0280 -8.8560 1.9590 CT 11 TRP -0.005000 + 177 HB2 -1.0370 -9.0480 2.3230 HC 11 TRP 0.033900 + 178 HB3 -0.0990 -7.8510 1.5440 HC 11 TRP 0.033900 + 179 CG 0.9470 -8.8980 3.0920 C* 11 TRP -0.141500 + 180 CD1 2.2900 -8.7630 3.0290 CW 11 TRP -0.163800 + 181 HD1 2.8540 -8.4010 2.1820 H4 11 TRP 0.206200 + 182 NE1 2.8150 -8.7140 4.3050 NA 11 TRP -0.341800 + 183 HE1 3.7790 -8.4650 4.4760 H 11 TRP 0.341200 + 184 CE2 1.8460 -8.7790 5.2860 CN 11 TRP 0.138000 + 185 CZ2 1.8110 -8.9290 6.6770 CA 11 TRP -0.260100 + 186 HZ2 2.7010 -8.9460 7.2880 HA 11 TRP 0.157200 + 187 CH2 0.5980 -9.0020 7.3730 CA 11 TRP -0.113400 + 188 HH2 0.6590 -9.0020 8.4510 HA 11 TRP 0.141700 + 189 CZ3 -0.5990 -9.1240 6.6570 CA 11 TRP -0.197200 + 190 HZ3 -1.5920 -9.3360 7.0260 HA 11 TRP 0.144700 + 191 CE3 -0.5300 -9.0320 5.2620 CA 11 TRP -0.238700 + 192 HE3 -1.5190 -9.0610 4.8280 HA 11 TRP 0.170000 + 193 CD2 0.6570 -8.9100 4.5220 CB 11 TRP 0.124300 + 194 C 0.3160 -11.2450 1.4220 C 11 TRP 0.597300 + 195 O -0.7630 -11.8050 1.5990 O 11 TRP -0.567900 + 196 N 1.4410 -11.9420 1.6040 N 12 LYS -0.347900 + 197 H 2.2820 -11.4040 1.4520 H 12 LYS 0.274700 + 198 CA 1.6320 -13.3040 2.0600 CT 12 LYS -0.240000 + 199 HA 0.8340 -13.9060 1.6260 H1 12 LYS 0.142600 + 200 CB 2.9560 -13.9260 1.6270 CT 12 LYS -0.009400 + 201 HB2 2.9780 -14.9900 1.8610 HC 12 LYS 0.036200 + 202 HB3 3.8390 -13.4820 2.0880 HC 12 LYS 0.036200 + 203 CG 3.1010 -13.8800 0.1090 CT 12 LYS 0.018700 + 204 HG2 2.8830 -12.8710 -0.2420 HC 12 LYS 0.010300 + 205 HG3 2.3180 -14.5660 -0.2160 HC 12 LYS 0.010300 + 206 CD 4.5080 -14.3900 -0.1850 CT 12 LYS -0.047900 + 207 HD2 4.7170 -15.2530 0.4480 HC 12 LYS 0.062100 + 208 HD3 5.2810 -13.7060 0.1660 HC 12 LYS 0.062100 + 209 CE 4.7390 -14.7580 -1.6480 CT 12 LYS -0.014300 + 210 HE2 4.5210 -13.8470 -2.2050 HP 12 LYS 0.113500 + 211 HE3 4.0020 -15.4760 -2.0080 HP 12 LYS 0.113500 + 212 NZ 6.1190 -15.2430 -1.7980 N3 12 LYS -0.385400 + 213 HZ1 6.3870 -15.4340 -2.7530 H 12 LYS 0.340000 + 214 HZ2 6.7080 -14.4820 -1.4910 H 12 LYS 0.340000 + 215 HZ3 6.3550 -16.0830 -1.2900 H 12 LYS 0.340000 + 216 C 1.4840 -13.4730 3.5660 C 12 LYS 0.734100 + 217 O 0.8230 -14.3180 4.1640 O 12 LYS -0.589400 + 218 N 2.1700 -12.4860 4.1480 N 13 NME -0.415700 + 219 H 2.7790 -11.9230 3.5710 H 13 NME 0.271900 + 220 CH3 2.1880 -12.2590 5.5790 CT 13 NME -0.149000 + 221 HH31 1.2430 -11.8100 5.8840 H1 13 NME 0.097600 + 222 HH32 2.4840 -13.1240 6.1720 H1 13 NME 0.097600 + 223 HH33 3.0220 -11.5670 5.6970 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** +@MOLECULE +Cpptraj Generated mol2 file. + 223 230 13 0 0 +SMALL +USER_CHARGES + + +@ATOM + 1 N -1.8890 9.1590 7.5690 N3 1 SER 0.184900 + 2 H1 -1.0370 8.6910 7.2960 H 1 SER 0.189800 + 3 H2 -1.9000 9.2980 8.5690 H 1 SER 0.189800 + 4 H3 -2.5380 8.4470 7.2650 H 1 SER 0.189800 + 5 CA -2.0640 10.5010 6.9930 CT 1 SER 0.056700 + 6 HA -3.1000 10.8240 7.1020 HP 1 SER 0.078200 + 7 CB -1.2300 11.5610 7.7070 CT 1 SER 0.259600 + 8 HB2 -1.6700 11.8110 8.6730 H1 1 SER 0.027300 + 9 HB3 -1.2480 12.5030 7.1590 H1 1 SER 0.027300 + 10 OG 0.1230 11.2160 7.9040 OH 1 SER -0.671400 + 11 HG 0.2740 11.7280 8.7010 HO 1 SER 0.423900 + 12 C -1.6130 10.4180 5.5420 C 1 SER 0.616300 + 13 O -2.4980 10.4330 4.6890 O 1 SER -0.572200 + 14 N -0.3660 10.5720 5.0900 N 2 TRP -0.415700 + 15 H 0.3440 10.6120 5.8080 H 2 TRP 0.271900 + 16 CA 0.1950 10.6970 3.7600 CT 2 TRP -0.027500 + 17 HA -0.2180 11.5690 3.2540 H1 2 TRP 0.112300 + 18 CB 1.7100 10.8790 3.7090 CT 2 TRP -0.005000 + 19 HB2 2.2080 9.9860 4.0870 HC 2 TRP 0.033900 + 20 HB3 1.9270 11.6410 4.4580 HC 2 TRP 0.033900 + 21 CG 2.2650 11.2910 2.3840 C* 2 TRP -0.141500 + 22 CD1 2.0320 12.5000 1.8270 CW 2 TRP -0.163800 + 23 HD1 1.5380 13.3330 2.3050 H4 2 TRP 0.206200 + 24 NE1 2.8600 12.5800 0.7240 NA 2 TRP -0.341800 + 25 HE1 2.9290 13.4040 0.1430 H 2 TRP 0.341200 + 26 CE2 3.6620 11.4600 0.6460 CN 2 TRP 0.138000 + 27 CZ2 4.6200 11.1600 -0.3300 CA 2 TRP -0.260100 + 28 HZ2 5.0590 11.8630 -1.0230 HA 2 TRP 0.157200 + 29 CH2 5.0910 9.8430 -0.3770 CA 2 TRP -0.113400 + 30 HH2 5.8540 9.6100 -1.1050 HA 2 TRP 0.141700 + 31 CZ3 4.5450 8.8500 0.4450 CA 2 TRP -0.197200 + 32 HZ3 4.8230 7.8400 0.1820 HA 2 TRP 0.144700 + 33 CE3 3.5490 9.1590 1.3790 CA 2 TRP -0.238700 + 34 HE3 3.1350 8.4300 2.0590 HA 2 TRP 0.170000 + 35 CD2 3.0750 10.4770 1.4830 CB 2 TRP 0.124300 + 36 C -0.1900 9.6090 2.7680 C 2 TRP 0.597300 + 37 O -0.4520 9.9630 1.6210 O 2 TRP -0.567900 + 38 N -0.2680 8.4020 3.3340 N 3 THR -0.415700 + 39 H -0.2600 8.2750 4.3360 H 3 THR 0.271900 + 40 CA -0.6060 7.1720 2.6470 CT 3 THR -0.038900 + 41 HA -0.1800 7.2660 1.6480 H1 3 THR 0.100700 + 42 CB -0.0930 5.9920 3.4680 CT 3 THR 0.365400 + 43 HB -0.5860 5.0810 3.1280 H1 3 THR 0.004300 + 44 CG2 1.3430 5.6480 3.0810 CT 3 THR -0.243800 + 45 HG21 1.3060 5.0050 2.2020 HC 3 THR 0.064200 + 46 HG22 1.9550 6.5430 2.9670 HC 3 THR 0.064200 + 47 HG23 1.8280 5.0680 3.8660 HC 3 THR 0.064200 + 48 OG1 -0.2730 6.2460 4.8430 OH 3 THR -0.676100 + 49 HG1 0.4280 5.7500 5.2710 HO 3 THR 0.410200 + 50 C -2.0730 6.8820 2.3630 C 3 THR 0.597300 + 51 O -2.8840 6.6850 3.2650 O 3 THR -0.567900 + 52 N -2.4140 6.7960 1.0750 N 4 TRP -0.415700 + 53 H -1.6310 6.7560 0.4390 H 4 TRP 0.271900 + 54 CA -3.6890 6.2860 0.6130 CT 4 TRP -0.027500 + 55 HA -4.2880 6.0200 1.4850 H1 4 TRP 0.112300 + 56 CB -4.4650 7.2750 -0.2530 CT 4 TRP -0.005000 + 57 HB2 -5.4500 6.8210 -0.3660 HC 4 TRP 0.033900 + 58 HB3 -4.0220 7.1620 -1.2420 HC 4 TRP 0.033900 + 59 CG -4.6320 8.7230 0.0770 C* 4 TRP -0.141500 + 60 CD1 -3.9020 9.7130 -0.4830 CW 4 TRP -0.163800 + 61 HD1 -3.0890 9.5530 -1.1760 H4 4 TRP 0.206200 + 62 NE1 -4.4730 10.9230 -0.1410 NA 4 TRP -0.341800 + 63 HE1 -4.1360 11.8610 -0.3060 H 4 TRP 0.341200 + 64 CE2 -5.4690 10.7460 0.7980 CN 4 TRP 0.138000 + 65 CZ2 -6.3300 11.6930 1.3650 CA 4 TRP -0.260100 + 66 HZ2 -6.2760 12.7460 1.1300 HA 4 TRP 0.157200 + 67 CH2 -7.3740 11.1960 2.1540 CA 4 TRP -0.113400 + 68 HH2 -8.2300 11.8220 2.3620 HA 4 TRP 0.141700 + 69 CZ3 -7.6300 9.8240 2.2590 CA 4 TRP -0.197200 + 70 HZ3 -8.3790 9.4820 2.9590 HA 4 TRP 0.144700 + 71 CE3 -6.7760 8.9050 1.6380 CA 4 TRP -0.238700 + 72 HE3 -6.9740 7.8720 1.8840 HA 4 TRP 0.170000 + 73 CD2 -5.7030 9.3470 0.8480 CB 4 TRP 0.124300 + 74 C -3.6320 4.9260 -0.0680 C 4 TRP 0.597300 + 75 O -4.2790 3.9520 0.3090 O 4 TRP -0.567900 + 76 N -2.7950 4.8720 -1.1060 N 5 GLU -0.516300 + 77 H -2.2780 5.7080 -1.3390 H 5 GLU 0.293600 + 78 CA -2.5350 3.7230 -1.9500 CT 5 GLU 0.039700 + 79 HA -3.0070 2.9480 -1.3460 H1 5 GLU 0.110500 + 80 CB -3.4130 3.5240 -3.1830 CT 5 GLU 0.056000 + 81 HB2 -3.1390 4.1410 -4.0380 HC 5 GLU -0.017300 + 82 HB3 -4.3860 3.7870 -2.7670 HC 5 GLU -0.017300 + 83 CG -3.4700 2.1080 -3.7480 CT 5 GLU 0.013600 + 84 HG2 -2.4470 1.7930 -3.9530 HC 5 GLU -0.042500 + 85 HG3 -4.0390 2.4250 -4.6230 HC 5 GLU -0.042500 + 86 CD -4.1890 1.1230 -2.8370 C 5 GLU 0.805400 + 87 OE1 -3.8030 0.7710 -1.7020 O2 5 GLU -0.818800 + 88 OE2 -5.2630 0.6010 -3.2070 O2 5 GLU -0.818800 + 89 C -1.0580 3.5180 -2.2550 C 5 GLU 0.536600 + 90 O -0.3010 4.4140 -2.6190 O 5 GLU -0.581900 + 91 N -0.6680 2.2650 -2.0090 N 6 ASN -0.415700 + 92 H -1.3230 1.6560 -1.5390 H 6 ASN 0.271900 + 93 CA 0.6390 1.6960 -2.2670 CT 6 ASN 0.014300 + 94 HA 1.2390 2.4530 -2.7720 H1 6 ASN 0.104800 + 95 CB 1.4120 1.3660 -0.9930 CT 6 ASN -0.204100 + 96 HB2 2.2240 0.7030 -1.2910 HC 6 ASN 0.079700 + 97 HB3 0.7120 0.8820 -0.3110 HC 6 ASN 0.079700 + 98 CG 2.1540 2.5500 -0.3910 C 6 ASN 0.713000 + 99 OD1 2.8090 3.3470 -1.0580 O 6 ASN -0.593100 + 100 ND2 2.3590 2.5190 0.9280 N 6 ASN -0.919100 + 101 HD21 1.8690 1.8970 1.5560 H 6 ASN 0.419600 + 102 HD22 3.0240 3.1960 1.2720 H 6 ASN 0.419600 + 103 C 0.5090 0.4880 -3.1850 C 6 ASN 0.597300 + 104 O -0.4570 -0.2500 -3.0040 O 6 ASN -0.567900 + 105 N 1.4630 0.2470 -4.0870 N 7 GLY -0.415700 + 106 H 2.3720 0.6580 -3.9320 H 7 GLY 0.271900 + 107 CA 1.3990 -0.9020 -4.9670 CT 7 GLY -0.025200 + 108 HA2 2.1800 -0.8820 -5.7280 H1 7 GLY 0.069800 + 109 HA3 0.5010 -0.7990 -5.5760 H1 7 GLY 0.069800 + 110 C 1.4480 -2.2750 -4.3130 C 7 GLY 0.597300 + 111 O 0.7270 -2.5760 -3.3640 O 7 GLY -0.567900 + 112 N 2.3610 -3.1180 -4.8010 N 8 LYS -0.347900 + 113 H 3.0800 -2.7840 -5.4260 H 8 LYS 0.274700 + 114 CA 2.5410 -4.5140 -4.4580 CT 8 LYS -0.240000 + 115 HA 1.6270 -5.0150 -4.1380 H1 8 LYS 0.142600 + 116 CB 3.1230 -5.2830 -5.6410 CT 8 LYS -0.009400 + 117 HB2 2.4350 -5.2430 -6.4860 HC 8 LYS 0.036200 + 118 HB3 3.3350 -6.3180 -5.3720 HC 8 LYS 0.036200 + 119 CG 4.4160 -4.7460 -6.2480 CT 8 LYS 0.018700 + 120 HG2 5.3080 -4.9600 -5.6600 HC 8 LYS 0.010300 + 121 HG3 4.3930 -3.6740 -6.4390 HC 8 LYS 0.010300 + 122 CD 4.7260 -5.5030 -7.5360 CT 8 LYS -0.047900 + 123 HD2 3.9920 -5.2720 -8.3080 HC 8 LYS 0.062100 + 124 HD3 4.5840 -6.5430 -7.2410 HC 8 LYS 0.062100 + 125 CE 6.1480 -5.3380 -8.0660 CT 8 LYS -0.014300 + 126 HE2 6.5210 -6.2900 -8.4440 HP 8 LYS 0.113500 + 127 HE3 6.8480 -5.0250 -7.2900 HP 8 LYS 0.113500 + 128 NZ 6.1770 -4.4200 -9.2140 N3 8 LYS -0.385400 + 129 HZ1 6.0460 -3.5470 -8.7220 H 8 LYS 0.340000 + 130 HZ2 7.1310 -4.3920 -9.5460 H 8 LYS 0.340000 + 131 HZ3 5.4710 -4.5500 -9.9250 H 8 LYS 0.340000 + 132 C 3.5120 -4.5190 -3.2860 C 8 LYS 0.734100 + 133 O 4.6240 -5.0420 -3.2860 O 8 LYS -0.589400 + 134 N 2.9250 -4.2560 -2.1160 N 9 TRP -0.415700 + 135 H 2.0100 -3.8790 -2.3160 H 9 TRP 0.271900 + 136 CA 3.3410 -4.2620 -0.7280 CT 9 TRP -0.027500 + 137 HA 4.4100 -4.0450 -0.7240 H1 9 TRP 0.112300 + 138 CB 2.6250 -3.0680 -0.1040 CT 9 TRP -0.005000 + 139 HB2 1.5890 -3.2940 0.1480 HC 9 TRP 0.033900 + 140 HB3 2.8350 -2.1940 -0.7210 HC 9 TRP 0.033900 + 141 CG 3.2880 -2.4620 1.0910 C* 9 TRP -0.141500 + 142 CD1 2.9250 -2.4360 2.3930 CW 9 TRP -0.163800 + 143 HD1 1.9490 -2.7990 2.6780 H4 9 TRP 0.206200 + 144 NE1 3.8550 -1.8450 3.2240 NA 9 TRP -0.341800 + 145 HE1 3.8850 -1.8480 4.2340 H 9 TRP 0.341200 + 146 CE2 4.8270 -1.3030 2.4080 CN 9 TRP 0.138000 + 147 CZ2 5.9110 -0.4710 2.7140 CA 9 TRP -0.260100 + 148 HZ2 6.1390 -0.1560 3.7210 HA 9 TRP 0.157200 + 149 CH2 6.8410 -0.1410 1.7220 CA 9 TRP -0.113400 + 150 HH2 7.7250 0.4050 2.0180 HA 9 TRP 0.141700 + 151 CZ3 6.5840 -0.5900 0.4210 CA 9 TRP -0.197200 + 152 HZ3 7.2310 -0.2350 -0.3680 HA 9 TRP 0.144700 + 153 CE3 5.4240 -1.2970 0.0820 CA 9 TRP -0.238700 + 154 HE3 5.1390 -1.4650 -0.9460 HA 9 TRP 0.170000 + 155 CD2 4.4790 -1.6200 1.0690 CB 9 TRP 0.124300 + 156 C 2.9450 -5.5930 -0.1050 C 9 TRP 0.597300 + 157 O 3.0220 -6.6750 -0.6820 O 9 TRP -0.567900 + 158 N 2.5310 -5.6090 1.1640 N 10 THR -0.415700 + 159 H 2.7110 -4.7940 1.7310 H 10 THR 0.271900 + 160 CA 2.2540 -6.8740 1.8150 CT 10 THR -0.038900 + 161 HA 2.9820 -7.6670 1.6440 H1 10 THR 0.100700 + 162 CB 2.2070 -6.6220 3.3200 CT 10 THR 0.365400 + 163 HB 1.7220 -5.6670 3.5260 H1 10 THR 0.004300 + 164 CG2 1.4560 -7.6590 4.1490 CT 10 THR -0.243800 + 165 HG21 1.5810 -7.4640 5.2140 HC 10 THR 0.064200 + 166 HG22 0.4020 -7.4680 3.9460 HC 10 THR 0.064200 + 167 HG23 1.7250 -8.6400 3.7550 HC 10 THR 0.064200 + 168 OG1 3.4600 -6.5010 3.9540 OH 10 THR -0.676100 + 169 HG1 3.3850 -6.0970 4.8220 HO 10 THR 0.410200 + 170 C 0.8890 -7.3540 1.3440 C 10 THR 0.597300 + 171 O -0.1720 -6.7600 1.5240 O 10 THR -0.567900 + 172 N 0.9060 -8.5220 0.6990 N 11 TRP -0.415700 + 173 H 1.7230 -9.1150 0.7340 H 11 TRP 0.271900 + 174 CA -0.1880 -9.0660 -0.0800 CT 11 TRP -0.027500 + 175 HA -0.7370 -8.2200 -0.4950 H1 11 TRP 0.112300 + 176 CB 0.4120 -10.0100 -1.1170 CT 11 TRP -0.005000 + 177 HB2 1.1130 -10.7100 -0.6610 HC 11 TRP 0.033900 + 178 HB3 0.8870 -9.3680 -1.8590 HC 11 TRP 0.033900 + 179 CG -0.5390 -10.9280 -1.8160 C* 11 TRP -0.141500 + 180 CD1 -1.3130 -10.6860 -2.8980 CW 11 TRP -0.163800 + 181 HD1 -1.3370 -9.7640 -3.4600 H4 11 TRP 0.206200 + 182 NE1 -1.9710 -11.7860 -3.4110 NA 11 TRP -0.341800 + 183 HE1 -2.3840 -11.8640 -4.3300 H 11 TRP 0.341200 + 184 CE2 -1.9570 -12.7630 -2.4370 CN 11 TRP 0.138000 + 185 CZ2 -2.7850 -13.8650 -2.1910 CA 11 TRP -0.260100 + 186 HZ2 -3.6310 -14.0120 -2.8460 HA 11 TRP 0.157200 + 187 CH2 -2.6000 -14.7090 -1.0890 CA 11 TRP -0.113400 + 188 HH2 -3.3150 -15.4730 -0.8230 HA 11 TRP 0.141700 + 189 CZ3 -1.5180 -14.3450 -0.2780 CA 11 TRP -0.197200 + 190 HZ3 -1.3250 -14.9360 0.6040 HA 11 TRP 0.144700 + 191 CE3 -0.8090 -13.1460 -0.4190 CA 11 TRP -0.238700 + 192 HE3 -0.0380 -12.8340 0.2700 HA 11 TRP 0.170000 + 193 CD2 -1.0340 -12.2590 -1.4840 CB 11 TRP 0.124300 + 194 C -1.0790 -9.7520 0.9460 C 11 TRP 0.597300 + 195 O -0.7100 -10.6730 1.6720 O 11 TRP -0.567900 + 196 N -2.3440 -9.3260 0.9490 N 12 LYS -0.347900 + 197 H -2.4560 -8.3390 0.7700 H 12 LYS 0.274700 + 198 CA -3.4700 -9.9260 1.6360 CT 12 LYS -0.240000 + 199 HA -3.0970 -10.4390 2.5220 H1 12 LYS 0.142600 + 200 CB -4.3840 -8.8140 2.1420 CT 12 LYS -0.009400 + 201 HB2 -5.3890 -9.1120 2.4400 HC 12 LYS 0.036200 + 202 HB3 -4.4390 -8.0090 1.4090 HC 12 LYS 0.036200 + 203 CG -3.7990 -8.0920 3.3520 CT 12 LYS 0.018700 + 204 HG2 -2.8890 -7.5660 3.0640 HC 12 LYS 0.010300 + 205 HG3 -3.6910 -8.7240 4.2330 HC 12 LYS 0.010300 + 206 CD -4.8480 -7.0240 3.6500 CT 12 LYS -0.047900 + 207 HD2 -5.6910 -7.4110 4.2220 HC 12 LYS 0.062100 + 208 HD3 -5.1300 -6.4950 2.7400 HC 12 LYS 0.062100 + 209 CE -4.1080 -6.0190 4.5290 CT 12 LYS -0.014300 + 210 HE2 -3.1830 -5.6350 4.0990 HP 12 LYS 0.113500 + 211 HE3 -3.8850 -6.5530 5.4520 HP 12 LYS 0.113500 + 212 NZ -4.8770 -4.8020 4.8290 N3 12 LYS -0.385400 + 213 HZ1 -5.1320 -4.3050 3.9870 H 12 LYS 0.340000 + 214 HZ2 -5.7180 -4.9680 5.3620 H 12 LYS 0.340000 + 215 HZ3 -4.2500 -4.2630 5.4100 H 12 LYS 0.340000 + 216 C -4.3950 -10.7780 0.7790 C 12 LYS 0.734100 + 217 O -4.4830 -11.9390 1.1720 O 12 LYS -0.589400 + 218 N -4.8320 -10.2020 -0.3440 N 13 NME -0.415700 + 219 H -4.6470 -9.2390 -0.5870 H 13 NME 0.271900 + 220 CH3 -5.7200 -10.8660 -1.2770 CT 13 NME -0.149000 + 221 HH31 -5.5910 -11.9460 -1.3400 H1 13 NME 0.097600 + 222 HH32 -6.7570 -10.8860 -0.9420 H1 13 NME 0.097600 + 223 HH33 -5.7770 -10.3580 -2.2400 H1 13 NME 0.097600 +@BOND + 1 12 13 1 + 2 12 14 1 + 3 7 10 1 + 4 5 7 1 + 5 5 12 1 + 6 1 5 1 + 7 36 37 1 + 8 36 38 1 + 9 33 35 1 + 10 31 33 1 + 11 29 31 1 + 12 27 29 1 + 13 26 27 1 + 14 26 35 1 + 15 24 26 1 + 16 22 24 1 + 17 21 22 1 + 18 21 35 1 + 19 18 21 1 + 20 16 18 1 + 21 16 36 1 + 22 14 16 1 + 23 50 51 1 + 24 50 52 1 + 25 42 44 1 + 26 42 48 1 + 27 40 42 1 + 28 40 50 1 + 29 38 40 1 + 30 74 75 1 + 31 74 76 1 + 32 71 73 1 + 33 69 71 1 + 34 67 69 1 + 35 65 67 1 + 36 64 65 1 + 37 64 73 1 + 38 62 64 1 + 39 60 62 1 + 40 59 60 1 + 41 59 73 1 + 42 56 59 1 + 43 54 56 1 + 44 54 74 1 + 45 52 54 1 + 46 89 90 1 + 47 89 91 1 + 48 86 87 1 + 49 86 88 1 + 50 83 86 1 + 51 80 83 1 + 52 78 80 1 + 53 78 89 1 + 54 76 78 1 + 55 103 104 1 + 56 103 105 1 + 57 98 99 1 + 58 98 100 1 + 59 95 98 1 + 60 93 95 1 + 61 93 103 1 + 62 91 93 1 + 63 110 111 1 + 64 110 112 1 + 65 107 110 1 + 66 105 107 1 + 67 132 133 1 + 68 132 134 1 + 69 125 128 1 + 70 122 125 1 + 71 119 122 1 + 72 116 119 1 + 73 114 116 1 + 74 114 132 1 + 75 112 114 1 + 76 156 157 1 + 77 156 158 1 + 78 153 155 1 + 79 151 153 1 + 80 149 151 1 + 81 147 149 1 + 82 146 147 1 + 83 146 155 1 + 84 144 146 1 + 85 142 144 1 + 86 141 142 1 + 87 141 155 1 + 88 138 141 1 + 89 136 138 1 + 90 136 156 1 + 91 134 136 1 + 92 170 171 1 + 93 170 172 1 + 94 162 164 1 + 95 162 168 1 + 96 160 162 1 + 97 160 170 1 + 98 158 160 1 + 99 194 195 1 + 100 194 196 1 + 101 191 193 1 + 102 189 191 1 + 103 187 189 1 + 104 185 187 1 + 105 184 185 1 + 106 184 193 1 + 107 182 184 1 + 108 180 182 1 + 109 179 180 1 + 110 179 193 1 + 111 176 179 1 + 112 174 176 1 + 113 174 194 1 + 114 172 174 1 + 115 216 217 1 + 116 216 218 1 + 117 209 212 1 + 118 206 209 1 + 119 203 206 1 + 120 200 203 1 + 121 198 200 1 + 122 198 216 1 + 123 196 198 1 + 124 218 220 1 + 125 10 11 1 + 126 7 8 1 + 127 7 9 1 + 128 5 6 1 + 129 1 2 1 + 130 1 3 1 + 131 1 4 1 + 132 33 34 1 + 133 31 32 1 + 134 29 30 1 + 135 27 28 1 + 136 24 25 1 + 137 22 23 1 + 138 18 19 1 + 139 18 20 1 + 140 16 17 1 + 141 14 15 1 + 142 48 49 1 + 143 44 45 1 + 144 44 46 1 + 145 44 47 1 + 146 42 43 1 + 147 40 41 1 + 148 38 39 1 + 149 71 72 1 + 150 69 70 1 + 151 67 68 1 + 152 65 66 1 + 153 62 63 1 + 154 60 61 1 + 155 56 57 1 + 156 56 58 1 + 157 54 55 1 + 158 52 53 1 + 159 83 84 1 + 160 83 85 1 + 161 80 81 1 + 162 80 82 1 + 163 78 79 1 + 164 76 77 1 + 165 100 101 1 + 166 100 102 1 + 167 95 96 1 + 168 95 97 1 + 169 93 94 1 + 170 91 92 1 + 171 107 108 1 + 172 107 109 1 + 173 105 106 1 + 174 128 129 1 + 175 128 130 1 + 176 128 131 1 + 177 125 126 1 + 178 125 127 1 + 179 122 123 1 + 180 122 124 1 + 181 119 120 1 + 182 119 121 1 + 183 116 117 1 + 184 116 118 1 + 185 114 115 1 + 186 112 113 1 + 187 153 154 1 + 188 151 152 1 + 189 149 150 1 + 190 147 148 1 + 191 144 145 1 + 192 142 143 1 + 193 138 139 1 + 194 138 140 1 + 195 136 137 1 + 196 134 135 1 + 197 168 169 1 + 198 164 165 1 + 199 164 166 1 + 200 164 167 1 + 201 162 163 1 + 202 160 161 1 + 203 158 159 1 + 204 191 192 1 + 205 189 190 1 + 206 187 188 1 + 207 185 186 1 + 208 182 183 1 + 209 180 181 1 + 210 176 177 1 + 211 176 178 1 + 212 174 175 1 + 213 172 173 1 + 214 212 213 1 + 215 212 214 1 + 216 212 215 1 + 217 209 210 1 + 218 209 211 1 + 219 206 207 1 + 220 206 208 1 + 221 203 204 1 + 222 203 205 1 + 223 200 201 1 + 224 200 202 1 + 225 198 199 1 + 226 196 197 1 + 227 220 221 1 + 228 220 222 1 + 229 220 223 1 + 230 218 219 1 +@SUBSTRUCTURE + 1 SER 1 **** 0 **** **** + 2 TRP 14 **** 0 **** **** + 3 THR 38 **** 0 **** **** + 4 TRP 52 **** 0 **** **** + 5 GLU 76 **** 0 **** **** + 6 ASN 91 **** 0 **** **** + 7 GLY 105 **** 0 **** **** + 8 LYS 112 **** 0 **** **** + 9 TRP 134 **** 0 **** **** + 10 THR 158 **** 0 **** **** + 11 TRP 172 **** 0 **** **** + 12 LYS 196 **** 0 **** **** + 13 NME 218 **** 0 **** **** diff --git a/test/Test_Grid_Rotate_Simple/RunTest.sh b/test/Test_Grid_Rotate_Simple/RunTest.sh index 30ef34b85e..8a1e7ca57d 100755 --- a/test/Test_Grid_Rotate_Simple/RunTest.sh +++ b/test/Test_Grid_Rotate_Simple/RunTest.sh @@ -4,6 +4,8 @@ CleanFiles grid.in tyr.rmsfit.dx tyr.rmsfit.dcd tyr.gridfit.dx +TESTNAME='Grid rotation tests.' +Requires netcdf RunTyr() { INPUT='-i grid.in'