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.ecfp;
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    import com.google.common.base.Preconditions;
023    
024    /**
025     * ECFP parameters class.
026     *
027     * <p>Please note that this class is marked with @Beta annotation, so it can be subject of incompatible changes or
028     * removal in later releases.</p>
029     *
030     * @author Gabor Imre
031     * @author Laszlo Antal
032     *
033     */
034    
035    @Description(
036            shortName = "ECFP",
037            name = "Extended-Connectivity Fingerprint family (ECFP)",
038            description = "Extended-Connectivity Fingerprints (ECFPs) represent circular"
039            + " topological atomic neighborhoods of the"
040            + " chemical structure. Using a hashing algoritm"
041            + " an integer identifier is associated to each neighborhood."
042            + " The identifiers used to set bits in a fixed length binary vector.")
043    @BuilderClass(builderClass = EcfpParameters.Builder.class)
044    @Beta
045    @PublicAPI
046    public class EcfpParameters implements DescriptorParameters {
047    
048        /**
049         * Serial version.
050         */
051        private static final long serialVersionUID = 0;
052    
053    
054        // DEFAULTS ========================================================================================================
055    
056        /**
057         * Default diameter to use.
058         */
059        public static final int DEFAULT_ECFP_DIAMETER = 4;
060    
061        /**
062         * Default length (bit count) for ECFP - folded binary fingerprint representation.
063         */
064        public static final int DEFAULT_ECFP_LENGTH = 1024;
065    
066        /**
067         * Default ECFP atom typizer to use.
068         */
069        public static final EcfpAtomTypizers DEFAULT_ECFP_ATOMTYPIZER = EcfpAtomTypizers.ECFP;
070    
071        // PARAMETERS ======================================================================================================
072    
073        /**
074         * Diameter parameter.
075         */
076        private final int diameter;
077    
078        /**
079         * Fingerprint length (bit count).
080         */
081        private final int length;
082    
083        /**
084         * Atom typizer to use.
085         */
086        private final EcfpAtomTypizers atomTypizer;
087    
088    
089        @Override
090        public EcfpGenerator getDescriptorGenerator() {
091            final ConstructEcfpGenerator c = ServiceUtil.loadService(ConstructEcfpGenerator.class, true);
092            return c.constructEcfpGenerator(this);
093        }
094    
095        /**
096         * Constructor based on a builder.
097         *
098         * @param builder Builder which current state will be represented.
099         */
100        private EcfpParameters(Builder builder) {
101            this.diameter = builder.diameter;
102            this.length = builder.length;
103            this.atomTypizer = builder.atomTypizer;
104        }
105    
106        /**
107         * Constructor using the default settings.
108         */
109        public EcfpParameters() {
110            this(new Builder());
111        }
112    
113        /**
114         * Construct a builder for this parameter class, initialized to default.
115         *
116         * @return  Builder initialized to default settings
117         */
118        public static Builder createNewBuilder() {
119            return new Builder();
120        }
121    
122        @Override
123        public String toString() {
124            return "Diameter: " + this.diameter + ", length: " + this.length + ", atom typizer: " + this.atomTypizer;
125        }
126    
127    
128        // GETTERS =========================================================================================================
129    
130        /**
131         * The maximum diameter of the circular neighborhoods.
132         *
133         * @return Diameter considered
134         */
135        public int getDiameter() {
136            return this.diameter;
137        }
138    
139        /**
140         * Returns represented fingerprint length (bit count) setting.
141         *
142         * @return  Fingerprint length
143         */
144        public int getLength() {
145            return this.length;
146        }
147    
148        /**
149         * Atom typizer to use.
150         *
151         * @return  Atom typizer to use
152         */
153        public EcfpAtomTypizers getAtomTypizer() {
154            return this.atomTypizer;
155        }
156    
157        // HELPER INTERFACE FOR DI =========================================================================================
158        /**
159         * Interface representing ECFP generator constructor.
160         */
161        protected interface ConstructEcfpGenerator {
162            /**
163             * Constructor invocation.
164             *
165             * @param parameters    Generator parameters
166             * @return              Created generator
167             */
168            EcfpGenerator constructEcfpGenerator(EcfpParameters parameters);
169        }
170    
171    
172        // BUILDER CLASS ===================================================================================================
173    
174        /**
175         * Builder class for the immutable parameter object.
176         */
177        @Parametrized
178        public static class Builder implements ParameterBuilder<EcfpParameters> {
179    
180            /**
181             * Diameter.
182             */
183            @Parameter(order = 1)
184            @Description(
185                    shortName = "Diameter",
186                    name = "Diameter",
187                    description = "The maximum diameter of the circular neighborhoods considered for each atom.")
188            private int diameter;
189    
190            /**
191             * Fingerprint length.
192             */
193            @Parameter(order = 2)
194            @Description(
195                    shortName = "Length",
196                    name = "Fingerprint length",
197                    description = "The number ot bits used in the bit string representation.")
198            private int length;
199    
200    
201            /**
202             * Atom typing.
203             */
204            @Parameter(order = 3)
205            @Description(
206                    shortName = "Atom typing",
207                    name = "Atom typing shourtcut",
208                    description = "Shortcut to predefined atom typing settings to be used.")
209            private EcfpAtomTypizers atomTypizer;
210    
211            /**
212             * Constructor with default settings.
213             */
214            public Builder() {
215                this.diameter = EcfpParameters.DEFAULT_ECFP_DIAMETER;
216                this.length = EcfpParameters.DEFAULT_ECFP_LENGTH;
217                this.atomTypizer = EcfpParameters.DEFAULT_ECFP_ATOMTYPIZER;
218            }
219    
220            /**
221             * Constructor based on a parameter object.
222             *
223             * @param parameters Parameter object
224             */
225            public Builder(EcfpParameters parameters) {
226                this.diameter = parameters.getDiameter();
227                this.length = parameters.getLength();
228                this.atomTypizer = parameters.getAtomTypizer();
229            }
230    
231            /**
232             * Sets diameter.
233             *
234             * @param diameter Diameter to set
235             * @return Reference to this builder
236             * @throws IllegalArgumentException when the set diameter is a negative or odd number
237             */
238            public Builder diameter(int diameter) {
239                if (diameter < 0) {
240                    throw new IllegalArgumentException("Diameter should be non negative: " + diameter);
241                }
242                if (diameter % 2 != 0) {
243                    throw new IllegalArgumentException("Diameter should be multiple of 2: " + diameter);
244                }
245                this.diameter = diameter;
246                return this;
247            }
248    
249            /**
250             * Set fingerprint length, the bit count of the folded binary fingerprint representation.
251             *
252             * @param length    new length
253             * @return          Reference to this builder
254             * @throws          IllegalArgumentException when the set length is not a positive number, or not multiply of 32
255             */
256            public Builder length(int length) {
257                if (length <= 0) {
258                    throw new IllegalArgumentException("Length should be positive: " + length);
259                }
260                if (length % 32 != 0) {
261                    throw new IllegalArgumentException("Length should be multiple of 32: " + length);
262                }
263                this.length = length;
264                return this;
265            }
266    
267            /**
268             * Set atom typizer to use.
269             *
270             * @param atomTypizer  Atom typizer to use
271             * @return             Reference to this builder
272             */
273            public Builder atomTypizer(EcfpAtomTypizers atomTypizer) {
274                this.atomTypizer = Preconditions.checkNotNull(atomTypizer);
275                return this;
276            }
277    
278            @Override
279            public EcfpParameters build() {
280                return new EcfpParameters(this);
281            }
282        }
283    }