001    /*
002     * Copyright (c) 1998-2014 ChemAxon Ltd. All Rights Reserved.
003     *
004     * This software is the confidential and proprietary information of
005     * ChemAxon. You shall not disclose such Confidential Information
006     * and shall use it only in accordance with the terms of the agreements
007     * you entered into with ChemAxon.
008     *
009     */
010    
011    package com.chemaxon.descriptors.fingerprints.cfp;
012    
013    import com.chemaxon.apidiscovery.annotations.BuilderClass;
014    import com.chemaxon.apidiscovery.annotations.Description;
015    import com.chemaxon.apidiscovery.annotations.Parameter;
016    import com.chemaxon.apidiscovery.annotations.Parametrized;
017    import com.chemaxon.apidiscovery.interfaces.ParameterBuilder;
018    import com.chemaxon.apidiscovery.util.ServiceUtil;
019    import com.chemaxon.common.annotations.PublicAPI;
020    import com.chemaxon.descriptors.common.DescriptorParameters;
021    import com.google.common.annotations.Beta;
022    
023    /**
024     * CFP parameters class.
025     *
026     * <p>Please note that this class is marked with @Beta annotation, so it can be subject of incompatible changes or
027     * removal in later releases.</p>
028     *
029     * @author Gabor Imre
030     */
031    
032    @Description(
033            shortName = "CFP",
034            name = "ChemaAxon hashed fingerprint (CFP)",
035            description = "ChemAxon hashed fingerprints (CFP) represent linear structural features up to a given maximal"
036            + " path length. Also cyclic and branching features considered.")
037    @BuilderClass(builderClass = CfpParameters.Builder.class)
038    @Beta
039    @PublicAPI
040    public class CfpParameters implements DescriptorParameters {
041    
042        /**
043         * Serial version.
044         */
045        private static final long serialVersionUID = 0;
046    
047    
048        // DEFAULTS ========================================================================================================
049    
050        /**
051         * The maximum length of consecutive bonds in the linear paths that are considered during the fragmentation of the
052         * molecule.
053         *
054         * <p>The length of cyclic patterns is limited to a fixed ring size.</p>
055         */
056        public static final int DEFAULT_CFP_MAX_PATTERN_LENGTH = 7;
057    
058    
059        /**
060         * The number of bits used to code each pattern in the hashed binary vector representation.
061         */
062        public static final int DEFAULT_BITS_TO_SET_FOR_PATTERNS = 3;
063    
064        /**
065         * Default length (bit count) for CFP - folded binary fingerprint representation.
066         */
067        public static final int DEFAULT_CFP_LENGTH = 1024;
068    
069    
070        // PARAMETERS ======================================================================================================
071    
072        /**
073         * Bits set for each pattern.
074         */
075        private final int bitsPerPattern;
076    
077        /**
078         * Fingerprint length (bit count).
079         */
080        private final int length;
081    
082        /**
083         * Max pattern length considered (bond count).
084         */
085        private final int bondCount;
086    
087    
088        @Override
089        public CfpGenerator getDescriptorGenerator() {
090            final ConstructCfpGenerator c = ServiceUtil.loadService(ConstructCfpGenerator.class, true);
091            return c.constructCfpGenerator(this);
092        }
093    
094        /**
095         * Constructor based on a builder.
096         *
097         * @param builder Builder which current state will be represented.
098         */
099        private CfpParameters(Builder builder) {
100            this.length = builder.length;
101            this.bitsPerPattern = builder.bitsPerPattern;
102            this.bondCount = builder.bondCount;
103        }
104    
105        /**
106         * Constructor using the default settings.
107         */
108        public CfpParameters() {
109            this(new Builder());
110        }
111    
112        /**
113         * Construct a builder for this parameter class, initialized to default.
114         *
115         * @return  Builder initialized to default settings
116         */
117        public static Builder createNewBuilder() {
118            return new Builder();
119        }
120    
121    
122        @Override
123        public String toString() {
124            return "bond count: " + this.bondCount + " (bits per pattern: " + this.bitsPerPattern + ", length: "
125                    + this.length + ")";
126        }
127    
128        // GETTERS =========================================================================================================
129        /**
130         * Max pattern length considered (bond count).
131         *
132         * @return Max pattern length considered (bond count).
133         */
134        public int getBondCount() {
135            return this.bondCount;
136        }
137    
138        /**
139         *  Bits set for each pattern.
140         *
141         * @return  Bits set for each pattern.
142         */
143        public int getBitsPerPattern() {
144            return this.bitsPerPattern;
145        }
146    
147        /**
148         * Returns represented fingerprint length (bit count) setting.
149         *
150         * @return  Fingerprint length
151         */
152        public int getLength() {
153            return this.length;
154        }
155    
156        // HELPER INTERFACE FOR DI =========================================================================================
157        /**
158         * Interface representing CFP generator constructor.
159         */
160        protected interface ConstructCfpGenerator {
161            /**
162             * Constructor invocation.
163             *
164             * @param parameters    Generator parameters
165             * @return              Created generator
166             */
167            CfpGenerator constructCfpGenerator(CfpParameters parameters);
168        }
169    
170    
171    
172    
173    
174        // BUILDER CLASS ===================================================================================================
175    
176        /**
177         * Builder class for the immutable parameter object.
178         */
179        @Parametrized
180        public static class Builder implements ParameterBuilder<CfpParameters> {
181    
182            /**
183             * Feature size (bond count).
184             */
185            @Parameter(order = 1)
186            @Description(
187                    shortName = "BondCount",
188                    name = "Max pattern length (bond count)",
189                    description = "The maximum length of consecutive bonds in the linear paths that are considered during"
190                    + " the fragmentation of the molecule.")
191            private int bondCount;
192    
193            /**
194             * Bits per pattern
195             */
196            @Parameter(order = 2)
197            @Description(
198                    shortName = "BitCount",
199                    name = "Bits per pattern",
200                    description = "The number of bits used to code each pattern in the hashed binary vector "
201                    + "representation.")
202            private int bitsPerPattern;
203    
204    
205            /**
206             * Fingerprint length.
207             */
208            @Parameter(order = 3)
209            @Description(
210                    shortName = "Length",
211                    name = "Fingerprint length",
212                    description = "The number of bits used in the bit string representation.")
213            private int length;
214    
215    
216    
217            /**
218             * Constructor with default settings.
219             */
220            public Builder() {
221                this.bondCount = CfpParameters.DEFAULT_CFP_MAX_PATTERN_LENGTH;
222                this.length = CfpParameters.DEFAULT_CFP_LENGTH;
223                this.bitsPerPattern = CfpParameters.DEFAULT_BITS_TO_SET_FOR_PATTERNS;
224            }
225    
226            /**
227             * Constructor based on a parameter object.
228             *
229             * @param parameters Parameter object
230             */
231            public Builder(CfpParameters parameters) {
232                this.bondCount = parameters.getBondCount();
233                this.length = parameters.getLength();
234                this.bitsPerPattern = parameters.getBitsPerPattern();
235    
236            }
237    
238            /**
239             * Set bond count to consider.
240             *
241             * <p>The maximum length of consecutive bonds in the linear paths that are considered during the fragmentation
242             * of the molecule.</p>
243             *
244             * @param bondCount     Bond count parameter to set. Use zero to consider no bonds, just atoms
245             * @return              Reference to this builder
246             * @throws IllegalArgumentException when the set diameter is a negative number
247             */
248            public Builder bondCount(int bondCount) {
249                if (bondCount < 0) {
250                    throw new IllegalArgumentException("Bond count should be non negative: " + bondCount);
251                }
252                this.bondCount = bondCount;
253                return this;
254            }
255    
256            /**
257             * Set fingerprint length, the bit count of the folded binary fingerprint representation.
258             *
259             * @param length    new length
260             * @return          Reference to this builder
261             * @throws          IllegalArgumentException when the set length is not a positive number, or not multiply of 32
262             */
263            public Builder length(int length) {
264                if (length <= 0) {
265                    throw new IllegalArgumentException("Length should be positive: " + length);
266                }
267                if (length % 32 != 0) {
268                    throw new IllegalArgumentException("Length should be multiple of 32: " + length);
269                }
270                this.length = length;
271                return this;
272            }
273    
274            /**
275             * Set bits per pattern.
276             *
277             * <p>The number of bits used to code each pattern in the hashed binary vector representation.</p>
278             *
279             * @param bitsPerPattern    Bits per pattern parameter
280             * @return                  Reference to this builder
281             * @throws                  IllegalArgumentException when parameter's value is less than one
282             */
283            public Builder bitsPerPattern(int bitsPerPattern) {
284                if (bitsPerPattern < 1) {
285                    throw new IllegalArgumentException("Bits per pattern should be no less than one: " + bitsPerPattern);
286                }
287                this.bitsPerPattern = bitsPerPattern;
288                return this;
289            }
290    
291            @Override
292            public CfpParameters build() {
293                return new CfpParameters(this);
294            }
295        }
296    }