    001/*-
    002 *******************************************************************************
    003 * Copyright (c) 2011, 2016 Diamond Light Source Ltd.
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the Eclipse Public License v1.0
    006 * which accompanies this distribution, and is available at
    007 * http://www.eclipse.org/legal/epl-v10.html
    008 *
    009 * Contributors:
    010 *    Peter Chang - initial API and implementation and/or initial documentation
    011 *******************************************************************************/
    012
    013package org.eclipse.january.dataset;
    014
    015import java.util.Date;
    016import java.util.List;
    017
    018public class DatasetFactory {
    019
    020        /**
    021         * Create dataset with items ranging from 0 up to given stop in steps of 1
    022         * @param stop stop value is <strong>not</strong> included
    023         * @param dtype dataset type
    024         * @return a new dataset of given shape and type, filled with values determined by parameters
    025         *
    026         * @deprecated Please use the class-based methods in DatasetFactory,
    027         *             such as {@link #createRange(Class, double)}
    028         */
    029        @Deprecated
    030        public static Dataset createRange(final double stop, final int dtype) {
    031                return createRange(0, stop, 1, dtype);
    032        }
    033
    034        /**
    035         * Create dataset with items ranging from given start up to given stop in given steps
    036         * @param start start value start value
    037         * @param stop stop value is <strong>not</strong> included
    038         * @param step spacing between items
    039         * @param dtype dataset type
    040         * @return a new 1D dataset of given type, filled with values determined by parameters
    041         *
    042         * @deprecated Please use the class-based methods in DatasetFactory,
    043         *             such as {@link #createRange(Class, double, double, double)}
    044         */
    045        @Deprecated
    046        public static Dataset createRange(final double start, final double stop, final double step, final int dtype) {
    047                return createRange(DTypeUtils.getInterface(dtype), start, stop, step);
    048        }
    049
    050        /**
    051         * Create compound dataset with items of given size ranging from 0 up to given stop in steps of 1
    052         * @param itemSize item size
    053         * @param stop stop value is <strong>not</strong> included
    054         * @param dtype dataset type
    055         * @return a new dataset of given shape and type, filled with values determined by parameters
    056         *
    057         * @deprecated Please use the class-based methods in DatasetFactory,
    058         *             such as {@link #createRange(int, Class, double)}
    059         */
    060        @Deprecated
    061        public static CompoundDataset createRange(final int itemSize, final double stop, final int dtype) {
    062                return createRange(itemSize, 0, stop, 1, dtype);
    063        }
    064
    065        /**
    066         * Create compound dataset with items of given size ranging from given start up to given stop in given steps
    067         * @param itemSize item size
    068         * @param start start value
    069         * @param stop stop value is <strong>not</strong> included
    070         * @param step spacing between items
    071         * @param dtype dataset type
    072         * @return a new 1D dataset of given type, filled with values determined by parameters
    073         *
    074         * @deprecated Please use the class-based methods in DatasetFactory,
    075         *             such as {@link #createRange(int, Class, double, double, double)}
    076         */
    077        @Deprecated
    078        public static CompoundDataset createRange(final int itemSize, final double start, final double stop, final double step, final int dtype) {
    079                Class<? extends CompoundDataset> clazz = InterfaceUtils.getCompoundInterface(DTypeUtils.getInterface(dtype));
    080                return createRange(itemSize, clazz, start, stop, step);
    081        }
    082
    083        /**
    084         * Create a dataset from object
    085         * @param dtype dataset type
    086         * @param obj
    087         *            can be a Java list, array or Number
    088         * @return dataset
    089         * @throws IllegalArgumentException if dataset type is not known
    090         *
    091         * @deprecated Please use the class-based methods in DatasetFactory,
    092         *             such as {@link #createFromObject(Class, Object, int...)}
    093         */
    094        @Deprecated
    095        public static Dataset createFromObject(final int dtype, final Object obj) {
    096                return createFromObject(dtype, obj, null);
    097        }
    098
    099        /**
    100         * Create a dataset from object
    101         * @param dtype dataset type
    102         * @param obj
    103         *            can be a Java list, array or Number
    104         * @param shape can be null
    105         * @return dataset
    106         * @throws IllegalArgumentException if dataset type is not known
    107         *
    108         * @deprecated Please use the class-based methods in DatasetFactory,
    109         *             such as {@link #createFromObject(Class, Object, int...)}
    110         */
    111        @Deprecated
    112        public static Dataset createFromObject(final int dtype, final Object obj, final int... shape) {
    113                return createFromObject(1, dtype, obj, shape);
    114        }
    115
    116        /**
    117         * Create a dataset from object
    118         * @param itemSize item size
    119         * @param dtype dataset type
    120         * @param obj
    121         *            can be a Java list, array or Number
    122         * @param shape can be null
    123         * @return dataset
    124         * @throws IllegalArgumentException if dataset type is not known
    125         *
    126         * @deprecated Please use the class-based methods in DatasetFactory,
    127         *             such as {@link #createFromObject(int, Class, Object, int...)}
    128         */
    129        @Deprecated
    130        public static Dataset createFromObject(final int itemSize, final int dtype, final Object obj, final int... shape) {
    131                return createFromObject(itemSize, DTypeUtils.getInterface(dtype), obj, shape);
    132        }
    133
    134        /**
    135         * Create dataset of given type from list
    136         *
    137         * @param dtype dataset type
    138         * @param objectList inputs
    139         * @return dataset filled with values from list
    140         *
    141         * @deprecated Please use the class-based methods in DatasetFactory,
    142         *             such as {@link #createFromList(Class, List)}
    143         */
    144        @Deprecated
    145        public static Dataset createFromList(final int dtype, List<?> objectList) {
    146                return createFromList(DTypeUtils.getInterface(dtype), objectList);
    147        }
    148
    149        /**
    150         * Create compound dataset of given type from given parts
    151         *
    152         * @param dtype dataset type
    153         * @param objects inputs
    154         * @return compound dataset
    155         *
    156         * @deprecated Please use the class-based methods in DatasetFactory,
    157         *             such as {@link #createCompoundDataset(Class, Object...)}
    158         */
    159        @Deprecated
    160        public static CompoundDataset createCompoundDataset(final int dtype, Object... objects) {
    161                return (CompoundDataset) createCompoundDataset(DTypeUtils.getInterface(dtype), objects);
    162        }
    163
    164        /**
    165         * Create complex dataset of given type from real and imaginary parts
    166         *
    167         * @param dtype dataset type
    168         * @param real real part
    169         * @param imag imaginary part
    170         * @return complex dataset
    171         *
    172         * @deprecated Please use the class-based methods in DatasetFactory,
    173         *             such as {@link #createComplexDataset(Class, Object, Object)}
    174         */
    175        @Deprecated
    176        public static CompoundDataset createComplexDataset(final int dtype, Object real, Object imag) {
    177                return createComplexDataset(DTypeUtils.getInterface(dtype), real, imag);
    178        }
    179
    180        /**
    181         * @param shape output shape
    182         * @param dtype dataset type
    183         * @return a new dataset of given shape and type, filled with zeros
    184         *
    185         * @deprecated Please use the class-based methods in DatasetFactory,
    186         *             such as {@link #zeros(Class, int...)}
    187         */
    188        @Deprecated
    189        public static Dataset zeros(final int[] shape, final int dtype) {
    190                return zeros(DTypeUtils.getInterface(dtype), shape);
    191        }
    192
    193        /**
    194         * @param itemSize item size
    195         *            if equal to 1, then non-compound dataset is returned
    196         * @param shape output shape
    197         * @param dtype dataset type
    198         * @return a new dataset of given item size, shape and type, filled with zeros
    199         *
    200         * @deprecated Please use the class-based methods in DatasetFactory,
    201         *             such as {@link #zeros(int, Class, int...)}
    202         */
    203        @Deprecated
    204        public static Dataset zeros(final int itemSize, final int[] shape, final int dtype) {
    205                if (itemSize == 1) {
    206                        return zeros(shape, dtype);
    207                }
    208                return compoundZeros(itemSize, shape, dtype);
    209        }
    210
    211        /**
    212         * @param itemSize item size
    213         * @param shape output shape
    214         * @param dtype dataset type
    215         * @return a new dataset of given item size, shape and type, filled with zeros
    216         * @since 2.0
    217         *
    218         * @deprecated Please use the class-based methods in DatasetFactory,
    219         *             such as {@link #compoundZeros(int, Class, int...)}
    220         */
    221        @Deprecated
    222        public static CompoundDataset compoundZeros(final int itemSize, final int[] shape, final int dtype) {
    223                return compoundZeros(itemSize, InterfaceUtils.getCompoundInterface(DTypeUtils.getInterface(dtype)), shape);
    224        }
    225
    226        /**
    227         * Create a new dataset of same shape as input dataset, filled with zeros. If dtype is not
    228         * explicitly compound then an elemental dataset is created
    229         * @param dataset input
    230         * @param dtype dataset type
    231         * @return a new dataset
    232         *
    233         * @deprecated Please use the class-based methods in DatasetFactory,
    234         *             such as {@link #zeros(Dataset, Class)}
    235         */
    236        @Deprecated
    237        public static Dataset zeros(final Dataset dataset, final int dtype) {
    238                Class<? extends Dataset> clazz = DTypeUtils.getInterface(dtype);
    239                final int isize = InterfaceUtils.isElemental(clazz) ? 1 :dataset.getElementsPerItem();
    240
    241                return zeros(isize, clazz, dataset.getShapeRef());
    242        }
    243
    244        /**
    245         * Create a new dataset of same shape as input dataset, filled with ones. If dtype is not
    246         * explicitly compound then an elemental dataset is created
    247         * @param dataset input
    248         * @param dtype dataset type
    249         * @return a new dataset
    250         *
    251         * @deprecated Please use the class-based methods in DatasetFactory,
    252         *             such as {@link #ones(Dataset, Class)}
    253         */
    254        @Deprecated
    255        public static Dataset ones(final Dataset dataset, final int dtype) {
    256                Class<? extends Dataset> clazz = DTypeUtils.getInterface(dtype);
    257                final int isize = InterfaceUtils.isElemental(clazz) ? 1 :dataset.getElementsPerItem();
    258
    259                return ones(isize, clazz, dataset.getShapeRef());
    260        }
    261
    262        /**
    263         * @param shape output shape
    264         * @param dtype dataset type
    265         * @return a new dataset of given shape and type, filled with ones
    266         *
    267         * @deprecated Please use the class-based methods in DatasetFactory,
    268         *             such as {@link #ones(Class, int...)}
    269         */
    270        @Deprecated
    271        public static Dataset ones(final int[] shape, final int dtype) {
    272                return ones(DTypeUtils.getInterface(dtype), shape);
    273        }
    274
    275        /**
    276         * @param itemSize item size
    277         *            if equal to 1, then non-compound dataset is returned
    278         * @param shape output shape
    279         * @param dtype dataset type
    280         * @return a new dataset of given item size, shape and type, filled with ones
    281         *
    282         * @deprecated Please use the class-based methods in DatasetFactory,
    283         *             such as {@link #ones(Class, int...)}
    284         */
    285        @Deprecated
    286        public static Dataset ones(final int itemSize, final int[] shape, final int dtype) {
    287                return ones(itemSize, DTypeUtils.getInterface(dtype), shape);
    288        }
    289
    290        /**
    291         * Create a 1D dataset of linearly spaced values in closed interval
    292         *
    293         * @param start start value
    294         * @param stop stop value is included
    295         * @param length number of points
    296         * @param dtype dataset type
    297         * @return dataset with linearly spaced values
    298         *
    299         * @deprecated Please use the class-based methods in DatasetFactory,
    300         *             such as {@link #createLinearSpace(Class, double, double, int)}
    301         */
    302        @Deprecated
    303        public static Dataset createLinearSpace(final double start, final double stop, final int length, final int dtype) {
    304                return createLinearSpace(DTypeUtils.getInterface(dtype), start, stop, length);
    305        }
    306
    307        /**
    308         * Create a 1D dataset of logarithmically spaced values in closed interval. The base value is used to
    309         * determine the factor between values: factor = base ** step, where step is the interval between linearly
    310         * spaced sequence of points
    311         *
    312         * @param start start value
    313         * @param stop stop value is included
    314         * @param length number of points
    315         * @param base for exponentiation
    316         * @param dtype dataset type
    317         * @return dataset with logarithmically spaced values
    318         *
    319         * @deprecated Please use the class-based methods in DatasetFactory,
    320         *             such as {@link #createLogSpace(Class, double, double, int, double)}
    321         */
    322        @Deprecated
    323        public static Dataset createLogSpace(final double start, final double stop, final int length, final double base, final int dtype) {
    324                return createLogSpace(DTypeUtils.getInterface(dtype), start, stop, length, base);
    325        }
    326
    327        /**
    328         * Create a 1D dataset of linearly spaced values in closed interval
    329         *
    330         * @param <T> dataset sub-interface
    331         * @param clazz dataset sub-interface
    332         * @param start start value
    333         * @param stop stop value is included
    334         * @param length number of points
    335         * @return dataset with linearly spaced values
    336         */
    337        public static <T extends Dataset> T createLinearSpace(Class<T> clazz, final double start, final double stop, final int length) {
    338                if (length < 1) {
    339                        throw new IllegalArgumentException("Length is less than one");
    340                } else if (length == 1) {
    341                        return createFromObject(clazz, start);
    342                } else {
    343                        T ds = zeros(clazz, length);
    344                        double num = stop - start;
    345                        double den = length - 1;
    346                        double value;
    347
    348                        for (int i = 0; i < length; i++) {
    349                                value = start + (num * i) / den;
    350                                ds.setObjectAbs(i, value);
    351                        }
    352
    353                        return ds;
    354                }
    355        }
    356
    357        /**
    358         * Create a 1D dataset of logarithmically spaced values in closed interval. The base value is used to
    359         * determine the factor between values: factor = base ** step, where step is the interval between linearly
    360         * spaced sequence of points
    361         *
    362         * @param <T> dataset sub-interface
    363         * @param clazz dataset sub-interface
    364         * @param start start value
    365         * @param stop stop value is included
    366         * @param length number of points
    367         * @param base for exponentiation
    368         * @return dataset with logarithmically spaced values
    369         */
    370        public static <T extends Dataset> T createLogSpace(Class<T> clazz, final double start, final double stop, final int length, final double base) {
    371                if (length < 1) {
    372                        throw new IllegalArgumentException("Length is less than one");
    373                } else if (length == 1) {
    374                        return createFromObject(clazz, Math.pow(base, start));
    375                } else {
    376                        T ds = zeros(clazz, length);
    377                        double step = (stop - start) / (length - 1);
    378                        double value;
    379
    380                        for (int i = 0; i < length; i++) {
    381                                value = start + i * step;
    382                                ds.setObjectAbs(i, Math.pow(base, value));
    383                        }
    384
    385                        return ds;
    386                }
    387        }
    388
    389        /**
    390         * Create dataset with items ranging from 0 up to given stop in steps of 1
    391         * @param stop stop value is <strong>not</strong> included
    392         * @return a new double dataset of given shape and type, filled with values determined by parameters
    393         */
    394        public static DoubleDataset createRange(final double stop) {
    395                return createRange(DoubleDataset.class, 0, stop, 1);
    396        }
    397
    398        /**
    399         * Create dataset with items ranging from given start up to given stop in given steps
    400         * @param start start value
    401         * @param stop stop value is <strong>not</strong> included
    402         * @param step spacing between items
    403         * @return a new 1D dataset of given type, filled with values determined by parameters
    404         * @since 2.1
    405         */
    406        public static DoubleDataset createRange(final double start, final double stop, final double step) {
    407                return createRange(DoubleDataset.class, start, stop, step);
    408        }
    409
    410        /**
    411         * Create dataset with items ranging from 0 up to given stop in steps of 1
    412         * @param <T> dataset sub-interface
    413         * @param clazz dataset sub-interface
    414         * @param stop stop value is <strong>not</strong> included
    415         * @return a new dataset of given shape and class, filled with values determined by parameters
    416         */
    417        public static <T extends Dataset> T createRange(Class<T> clazz, final double stop) {
    418                return createRange(clazz, 0, stop, 1);
    419        }
    420
    421        /**
    422         * Create dataset with items ranging from given start up to given stop in given steps
    423         * @param <T> dataset sub-interface
    424         * @param clazz dataset sub-interface
    425         * @param start start value
    426         * @param stop stop value is <strong>not</strong> included
    427         * @param step spacing between items
    428         * @return a new 1D dataset of given class, filled with values determined by parameters
    429         */
    430        @SuppressWarnings("unchecked")
    431        public static <T extends Dataset> T createRange(Class<T> clazz, final double start, final double stop, final double step) {
    432                if ((step > 0) != (start <= stop)) {
    433                        throw new IllegalArgumentException("Invalid parameters: start and stop must be in correct order for step");
    434                }
    435
    436                Dataset d = null;
    437                if (ByteDataset.class.isAssignableFrom(clazz)) {
    438                        d = ByteDataset.createRange(start, stop, step);
    439                } else if (ShortDataset.class.isAssignableFrom(clazz)) {
    440                        d = ShortDataset.createRange(start, stop, step);
    441                } else if (IntegerDataset.class.isAssignableFrom(clazz)) {
    442                        d = IntegerDataset.createRange(start, stop, step);
    443                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    444                        d = LongDataset.createRange(start, stop, step);
    445                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    446                        d = FloatDataset.createRange(start, stop, step);
    447                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    448                        d = DoubleDataset.createRange(start, stop, step);
    449                } else if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    450                        d = ComplexFloatDataset.createRange(start, stop, step);
    451                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    452                        d = ComplexDoubleDataset.createRange(start, stop, step);
    453                } else {
    454                        throw new IllegalArgumentException("Dataset interface not supported");
    455                }
    456
    457                return (T) d;
    458        }
    459
    460        /**
    461         * Create compound dataset with items ranging from 0 up to given stop in steps of 1
    462         * @param <T> compound dataset sub-interface
    463         * @param itemSize item size
    464         * @param clazz compound dataset sub-interface
    465         * @param stop stop value is <strong>not</strong> included
    466         * @return a new 1D dataset of given class, filled with values determined by parameters
    467         * @since 2.1
    468         */
    469        public static <T extends CompoundDataset> T createRange(final int itemSize, Class<T> clazz, final double stop) {
    470                return createRange(itemSize, clazz, 0, stop, 1);
    471        }
    472
    473        /**
    474         * Create compound dataset with items ranging from given start up to given stop in given steps
    475         * @param <T> compound dataset sub-interface
    476         * @param itemSize item size
    477         * @param clazz compound dataset sub-interface
    478         * @param start start value
    479         * @param stop stop value is <strong>not</strong> included
    480         * @param step spacing between items
    481         * @return a new 1D dataset of given class, filled with values determined by parameters
    482         * @since 2.1
    483         */
    484        @SuppressWarnings("unchecked")
    485        public static <T extends CompoundDataset> T createRange(final int itemSize, Class<T> clazz, final double start, final double stop, final double step) {
    486                if (itemSize < 1) {
    487                        throw new IllegalArgumentException("Item size must be greater or equal to 1");
    488                }
    489                if ((step > 0) != (start <= stop)) {
    490                        throw new IllegalArgumentException("Invalid parameters: start and stop must be in correct order for step");
    491                }
    492
    493                CompoundDataset c = null;
    494                if (CompoundByteDataset.class.isAssignableFrom(clazz)) {
    495                        c = CompoundIntegerDataset.createRange(itemSize, start, stop, step);
    496                } else if (CompoundShortDataset.class.isAssignableFrom(clazz)) {
    497                        c = CompoundShortDataset.createRange(itemSize, start, stop, step);
    498                } else if (CompoundIntegerDataset.class.isAssignableFrom(clazz)) {
    499                        c = CompoundIntegerDataset.createRange(itemSize, start, stop, step);
    500                } else if (CompoundLongDataset.class.isAssignableFrom(clazz)) {
    501                        c = CompoundLongDataset.createRange(itemSize, start, stop, step);
    502                } else if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    503                        if (itemSize != 2) {
    504                                throw new IllegalArgumentException("Item size must be equal to 2");
    505                        }
    506                        c = ComplexFloatDataset.createRange(start, stop, step);
    507                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    508                        if (itemSize != 2) {
    509                                throw new IllegalArgumentException("Item size must be equal to 2");
    510                        }
    511                        c = ComplexDoubleDataset.createRange(start, stop, step);
    512                } else if (CompoundFloatDataset.class.isAssignableFrom(clazz)) {
    513                        c = CompoundFloatDataset.createRange(itemSize, start, stop, step);
    514                } else if (CompoundDoubleDataset.class.isAssignableFrom(clazz)) {
    515                        c = CompoundDoubleDataset.createRange(itemSize, start, stop, step);
    516                } else {
    517                        throw new IllegalArgumentException("dtype not known");
    518                }
    519                return (T) c;
    520        }
    521
    522        /**
    523         * Create a dataset from object (automatically detect dataset type)
    524         *
    525         * @param obj
    526         *            can be Java list, array or Number
    527         * @return dataset
    528         */
    529        public static Dataset createFromObject(Object obj) {
    530                return createFromObject(obj, null);
    531        }
    532
    533        /**
    534         * Create a dataset from object (automatically detect dataset type)
    535         *
    536         * @param obj
    537         *            can be Java list, array or Number
    538         * @param shape can be null
    539         * @return dataset
    540         */
    541        public static Dataset createFromObject(Object obj, int... shape) {
    542                if (obj instanceof IDataset) {
    543                        Dataset d = DatasetUtils.convertToDataset((IDataset) obj);
    544                        if (shape != null) {
    545                                d.setShape(shape);
    546                        }
    547                        return d;
    548                }
    549
    550                return createFromObject(InterfaceUtils.getInterface(obj), obj, shape);
    551        }
    552
    553        /**
    554         * Create a dataset from object (automatically detect dataset type)
    555         * @param isUnsigned
    556         *            if true, interpret integer values as unsigned by increasing element bit width if required
    557         * @param obj
    558         *            can be a Java list, array or Number
    559         * @return dataset
    560         */
    561        public static Dataset createFromObject(boolean isUnsigned, final Object obj) {
    562                Dataset a = createFromObject(obj);
    563                if (isUnsigned) {
    564                        a = DatasetUtils.makeUnsigned(a, true);
    565                }
    566                return a;
    567        }
    568
    569        /**
    570         * Create dataset of appropriate type from list
    571         *
    572         * @param objectList inputs for each item
    573         * @return dataset filled with values from list
    574         */
    575        public static Dataset createFromList(List<?> objectList) {
    576                if (objectList == null || objectList.size() == 0) {
    577                        throw new IllegalArgumentException("No list or zero-length list given");
    578                }
    579
    580                Object obj = null;
    581                for (Object o : objectList) {
    582                        if (o != null) {
    583                                obj = o;
    584                                break;
    585                        }
    586                }
    587                if (obj == null) {
    588                        return zeros(ObjectDataset.class, objectList.size());
    589                }
    590
    591                Class<? extends Object> clazz = obj.getClass();
    592                if (InterfaceUtils.isElementSupported(clazz)) {
    593                        return createFromList(InterfaceUtils.getInterface(obj), objectList);
    594                }
    595
    596                return createFromObject(objectList);
    597        }
    598
    599        /**
    600         * Create compound dataset of given type from given parts
    601         *
    602         * @param objects inputs across dataset for each element
    603         * @return compound dataset
    604         */
    605        public static CompoundDataset createCompoundDataset(Object... objects) {
    606                Dataset[] datasets = new Dataset[objects.length];
    607                for (int i = 0; i < objects.length; i++) {
    608                        datasets[i] = createFromObject(objects[i]);
    609                }
    610                return DatasetUtils.createCompoundDataset(datasets);
    611        }
    612
    613        /**
    614         * Create a dataset from object
    615         * @param <T> dataset sub-interface
    616         * @param clazz dataset sub-interface
    617         * @param obj
    618         *            can be a Java list, array or Number
    619         * @return dataset
    620         * @throws IllegalArgumentException if dataset class is not known
    621         * @since 2.1
    622         */
    623        public static <T extends Dataset> T createFromObject(Class<T> clazz, Object obj) {
    624                return createFromObject(1, clazz, obj, null);
    625        }
    626
    627
    628        /**
    629         * Create a dataset from object
    630         * @param <T> dataset sub-interface
    631         * @param clazz dataset sub-interface
    632         * @param obj
    633         *            can be a Java list, array or Number
    634         * @param shape can be null
    635         * @return dataset
    636         */
    637        public static <T extends Dataset> T createFromObject(Class<T> clazz, Object obj, int... shape) {
    638                return createFromObject(1, clazz, obj, shape);
    639        }
    640
    641        /**
    642         * Create a compound dataset from object
    643         * @param <T> compound dataset sub-interface
    644         * @param itemSize item size
    645         * @param clazz compound dataset sub-interface
    646         * @param obj
    647         *            can be a Java list, array or Number
    648         * @param shape can be null
    649         * @return dataset
    650         */
    651        @SuppressWarnings("unchecked")
    652        public static <T extends Dataset> T createFromObject(final int itemSize, Class<T> clazz, Object obj, int... shape) {
    653                Dataset d = null;
    654
    655                if (obj instanceof IDataset) {
    656                        d = itemSize == 1 ? DatasetUtils.cast(clazz, (IDataset) obj) :
    657                                DatasetUtils.cast(itemSize, clazz, (IDataset) obj, false);
    658                } else {
    659                        // primitive arrays
    660                        Class<? extends Object> ca = obj == null ? null : obj.getClass().getComponentType();
    661                        if (ca != null && (ca.isPrimitive() || ca.equals(String.class))) {
    662                                if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    663                                        return (T) new ComplexFloatDataset(DTypeUtils.toFloatArray(obj, DTypeUtils.getLength(obj)), shape);
    664                                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    665                                        return (T) new ComplexDoubleDataset(DTypeUtils.toDoubleArray(obj, DTypeUtils.getLength(obj)), shape);
    666                                } else {
    667                                        d = createFromPrimitiveArray(InterfaceUtils.getInterfaceFromClass(1, ca), obj);
    668                                        if (!InterfaceUtils.isElemental(clazz)) {
    669                                                if (RGBByteDataset.class.isAssignableFrom(clazz) || RGBDataset.class.isAssignableFrom(clazz)) {
    670                                                        d = DatasetUtils.createCompoundDataset(d, 3);
    671                                                        if (d.getSize() == 1) { // special case of allowing a zero-rank RGB dataset
    672                                                                d.setShape();
    673                                                        }
    674                                                } else {
    675                                                        d = DatasetUtils.createCompoundDataset(d, itemSize);
    676                                                }
    677                                        }
    678                                        d = d.cast(clazz);
    679                                }
    680                        } else {
    681//                              if (itemSize != 1 && !InterfaceUtils.isElemental(clazz)) {
    682//                                      throw new IllegalArgumentException("Compound dataset interface needed for itemSize > 1");
    683//                              }
    684                                if (BooleanDataset.class.isAssignableFrom(clazz)) {
    685                                        d = BooleanDataset.createFromObject(obj);
    686                                } else if (ByteDataset.class.isAssignableFrom(clazz)) {
    687                                        d = ByteDataset.createFromObject(obj);
    688                                } else if (ShortDataset.class.isAssignableFrom(clazz)) {
    689                                        d = ShortDataset.createFromObject(obj);
    690                                } else if (IntegerDataset.class.isAssignableFrom(clazz)) {
    691                                        d = IntegerDataset.createFromObject(obj);
    692                                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    693                                        d = LongDataset.createFromObject(obj);
    694                                } else if (RGBByteDataset.class.isAssignableFrom(clazz)) {
    695                                        d = RGBByteDataset.createFromObject(obj);
    696                                } else if (CompoundByteDataset.class.isAssignableFrom(clazz)) {
    697                                        d = CompoundByteDataset.createFromObject(itemSize, obj);
    698                                } else if (RGBDataset.class.isAssignableFrom(clazz)) {
    699                                        d = RGBDataset.createFromObject(obj);
    700                                } else if (CompoundShortDataset.class.isAssignableFrom(clazz)) {
    701                                        d = CompoundShortDataset.createFromObject(itemSize, obj);
    702                                } else if (CompoundIntegerDataset.class.isAssignableFrom(clazz)) {
    703                                        d = CompoundIntegerDataset.createFromObject(itemSize, obj);
    704                                } else if (CompoundLongDataset.class.isAssignableFrom(clazz)) {
    705                                        d = CompoundLongDataset.createFromObject(itemSize, obj);
    706                                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    707                                        d = FloatDataset.createFromObject(obj);
    708                                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    709                                        d = DoubleDataset.createFromObject(obj);
    710                                } else if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    711                                        d = ComplexFloatDataset.createFromObject(obj);
    712                                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    713                                        d = ComplexDoubleDataset.createFromObject(obj);
    714                                } else if (CompoundFloatDataset.class.isAssignableFrom(clazz)) {
    715                                        d = CompoundFloatDataset.createFromObject(itemSize, obj);
    716                                } else if (CompoundDoubleDataset.class.isAssignableFrom(clazz)) {
    717                                        d = CompoundDoubleDataset.createFromObject(itemSize, obj);
    718                                } else if (DateDataset.class.isAssignableFrom(clazz)) {
    719                                        d = DateDatasetImpl.createFromObject(obj);
    720                                } else if (StringDataset.class.isAssignableFrom(clazz)) {
    721                                        d = StringDataset.createFromObject(obj);
    722                                } else if (ObjectDataset.class.isAssignableFrom(clazz)) {
    723                                        d = ObjectDataset.createFromObject(obj);
    724                                } else {
    725                                        throw new IllegalArgumentException("Dataset interface is not unsupported");
    726                                }
    727                        }
    728                }
    729
    730                if (shape != null && !(shape.length == 0 && d.getSize() > 1)) { // allow zero-rank datasets
    731                        d.setShape(shape);
    732                }
    733                return (T) d;
    734        }
    735
    736        private static Dataset createFromPrimitiveArray(Class<? extends Dataset> clazz, final Object array) {
    737                if (BooleanDataset.class.isAssignableFrom(clazz)) {
    738                        return new BooleanDataset((boolean[]) array);
    739                } else if (ByteDataset.class.isAssignableFrom(clazz)) {
    740                        return new ByteDataset((byte[]) array);
    741                } else if (ShortDataset.class.isAssignableFrom(clazz)) {
    742                        return new ShortDataset((short[]) array);
    743                } else if (IntegerDataset.class.isAssignableFrom(clazz)) {
    744                        return new IntegerDataset((int[]) array, null);
    745                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    746                        return new LongDataset((long[]) array);
    747                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    748                        return new FloatDataset((float[]) array);
    749                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    750                        return new DoubleDataset((double[]) array);
    751                } else if (StringDataset.class.isAssignableFrom(clazz)) {
    752                        return new StringDataset((String[]) array);
    753                } else if (DateDataset.class.isAssignableFrom(clazz)) {
    754                        return new DateDatasetImpl((Date[]) array);
    755                }
    756                return null;
    757        }
    758
    759        /**
    760         * Create dataset of given class from list
    761         *
    762         * @param <T> dataset sub-interface
    763         * @param clazz dataset sub-interface
    764         * @param objectList inputs for each item
    765         * @return dataset filled with values from list
    766         */
    767        public static <T extends Dataset> T createFromList(Class<T> clazz, List<?> objectList) {
    768                int len = objectList.size();
    769                T result = zeros(clazz, len);
    770
    771                for (int i = 0; i < len; i++) {
    772                        result.setObjectAbs(i, objectList.get(i));
    773                }
    774                return result;
    775        }
    776
    777        /**
    778         * Create compound dataset of given class from given parts
    779         *
    780         * @param <T> compound dataset sub-interface
    781         * @param clazz compound dataset sub-interface
    782         * @param objects inputs across dataset for each element
    783         * @return compound dataset
    784         * @since 2.3
    785         */
    786        public static <T extends CompoundDataset> T createCompoundDataset(Class<T> clazz, Object... objects) {
    787                Dataset[] datasets = new Dataset[objects.length];
    788                for (int i = 0; i < objects.length; i++) {
    789                        datasets[i] = createFromObject(objects[i]);
    790                }
    791                return DatasetUtils.createCompoundDataset(clazz, datasets);
    792        }
    793
    794        /**
    795         * Create complex dataset of given class from real and imaginary parts
    796         *
    797         * @param <T> complex dataset sub-interface
    798         * @param clazz complex dataset sub-interface
    799         * @param real real part
    800         * @param imag imaginary part
    801         * @return complex dataset
    802         * @since 2.3
    803         */
    804        @SuppressWarnings("unchecked")
    805        public static <T extends CompoundDataset> T createComplexDataset(Class<? extends Dataset> clazz, Object real, Object imag) {
    806                if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    807                        return (T) new ComplexFloatDataset(createFromObject(real), createFromObject(imag));
    808                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    809                        return (T) new ComplexDoubleDataset(createFromObject(real), createFromObject(imag));
    810                } else {
    811                        throw new IllegalArgumentException("Dataset class must be a complex one");
    812                }
    813        }
    814
    815        /**
    816         * @param shape output shape
    817         * @return a new double dataset of given shape, filled with zeros
    818         */
    819        public static DoubleDataset zeros(final int... shape) {
    820                return zeros(DoubleDataset.class, shape);
    821        }
    822
    823        /**
    824         * @param <T> dataset subclass
    825         * @param dataset input
    826         * @return a new dataset of same shape and class as input dataset, filled with zeros
    827         */
    828        public static <T extends Dataset> T zeros(final T dataset) {
    829                return zeros(dataset, dataset.getShapeRef());
    830        }
    831
    832        /**
    833         * @param <T> dataset subclass
    834         * @param dataset input
    835         * @param shape output shape
    836         * @return a new dataset of same class as input dataset and given shape, filled with zeros
    837         * @since 2.3
    838         */
    839        @SuppressWarnings("unchecked")
    840        public static <T extends Dataset> T zeros(final T dataset, int... shape) {
    841                Class<? extends Dataset> clazz = dataset.getClass();
    842                return (T) (InterfaceUtils.isElemental(dataset.getClass()) ? zeros(clazz, shape) :
    843                        compoundZeros(dataset.getElementsPerItem(), InterfaceUtils.getCompoundInterface(clazz), shape));
    844        }
    845
    846        /**
    847         * @param <T> dataset sub-interface
    848         * @param clazz dataset sub-interface
    849         * @param shape output shape
    850         * @return a new dataset of given shape and class, filled with zeros
    851         */
    852        @SuppressWarnings("unchecked")
    853        public static <T extends Dataset> T zeros(Class<T> clazz, int... shape) {
    854                if (BooleanDataset.class.isAssignableFrom(clazz)) {
    855                        return (T) new BooleanDataset(shape);
    856                } else if (ByteDataset.class.isAssignableFrom(clazz)) {
    857                        return (T) new ByteDataset(shape);
    858                } else if (ShortDataset.class.isAssignableFrom(clazz)) {
    859                        return (T) new ShortDataset(shape);
    860                } else if (IntegerDataset.class.isAssignableFrom(clazz)) {
    861                        return (T) new IntegerDataset(shape);
    862                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    863                        return (T) new LongDataset(shape);
    864                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    865                        return (T) new FloatDataset(shape);
    866                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    867                        return (T) new DoubleDataset(shape);
    868                } else if (RGBByteDataset.class.isAssignableFrom(clazz)) {
    869                        return (T) new RGBByteDataset(shape);
    870                } else if (RGBDataset.class.isAssignableFrom(clazz)) {
    871                        return (T) new RGBDataset(shape);
    872                } else if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    873                        return (T) new ComplexFloatDataset(shape);
    874                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    875                        return (T) new ComplexDoubleDataset(shape);
    876                } else if (StringDataset.class.isAssignableFrom(clazz)) {
    877                        return (T) new StringDataset(shape);
    878                } else if (DateDataset.class.isAssignableFrom(clazz)) {
    879                        return (T) new DateDatasetImpl(shape);
    880                } else if (ObjectDataset.class.isAssignableFrom(clazz)) {
    881                        return (T) new ObjectDataset(shape);
    882                }
    883
    884                throw new IllegalArgumentException("Interface not known or unsupported");
    885        }
    886
    887        /**
    888         * @param <T> dataset sub-interface
    889         * @param itemSize item size. If equal to 1, then non-compound dataset is returned
    890         * @param clazz dataset sub-interface
    891         * @param shape output shape
    892         * @return a new dataset of given item size, shape and class, filled with zeros
    893         */
    894        @SuppressWarnings("unchecked")
    895        public static <T extends Dataset> T zeros(int itemSize, Class<T> clazz, int... shape) {
    896                if (itemSize == 1 && InterfaceUtils.isElemental(clazz)) {
    897                        return zeros(clazz, shape);
    898                }
    899                return (T) compoundZeros(itemSize, InterfaceUtils.getCompoundInterface(clazz), shape);
    900        }
    901
    902        /**
    903         * @param <T> dataset subclass
    904         * @param dataset input
    905         * @param clazz dataset class
    906         * @return a new dataset of given class with same shape as input dataset, filled with zeros
    907         */
    908        public static <T extends Dataset> T zeros(Dataset dataset, Class<T> clazz) {
    909                return (T) zeros(dataset.getElementsPerItem(), clazz, dataset.getShapeRef());
    910        }
    911
    912        /**
    913         * @param <T> compound dataset sub-interface
    914         * @param itemSize item size
    915         * @param clazz compound dataset sub-interface
    916         * @param shape output shape
    917         * @return a new compound dataset of given item size, shape and class, filled with zeros
    918         * @since 2.0
    919         */
    920        @SuppressWarnings("unchecked")
    921        public static <T extends CompoundDataset> T compoundZeros(int itemSize, Class<T> clazz, int... shape) {
    922                if (RGBByteDataset.class.isAssignableFrom(clazz)) {
    923                        if (itemSize != 3) {
    924                                throw new IllegalArgumentException("Number of elements not compatible with RGB type");
    925                        }
    926                        return (T) new RGBByteDataset(shape);
    927                } else if (CompoundByteDataset.class.isAssignableFrom(clazz)) {
    928                        return (T) new CompoundByteDataset(itemSize, shape);
    929                } else  if (RGBDataset.class.isAssignableFrom(clazz)) {
    930                        if (itemSize != 3) {
    931                                throw new IllegalArgumentException("Number of elements not compatible with RGB type");
    932                        }
    933                        return (T) new RGBDataset(shape);
    934                } else if (CompoundShortDataset.class.isAssignableFrom(clazz)) {
    935                        return (T) new CompoundShortDataset(itemSize, shape);
    936                } else if (CompoundIntegerDataset.class.isAssignableFrom(clazz)) {
    937                        return (T) new CompoundIntegerDataset(itemSize, shape);
    938                } else if (CompoundLongDataset.class.isAssignableFrom(clazz)) {
    939                        return (T) new CompoundLongDataset(itemSize, shape);
    940                } else if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    941                        if (itemSize != 2) {
    942                                throw new IllegalArgumentException("Number of elements not compatible with complex type");
    943                        }
    944                        return (T) new ComplexFloatDataset(shape);
    945                } else if (CompoundFloatDataset.class.isAssignableFrom(clazz)) {
    946                        return (T) new CompoundFloatDataset(itemSize, shape);
    947                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    948                        if (itemSize != 2) {
    949                                throw new IllegalArgumentException("Number of elements not compatible with complex type");
    950                        }
    951                        return (T) new ComplexDoubleDataset(shape);
    952                } else if (CompoundDoubleDataset.class.isAssignableFrom(clazz)) {
    953                        return (T) new CompoundDoubleDataset(itemSize, shape);
    954                }
    955                throw new IllegalArgumentException("Class not a known compound interface");
    956        }
    957
    958        /**
    959         * @param shape output shape
    960         * @return a new double dataset of given shape, filled with ones
    961         */
    962        public static DoubleDataset ones(final int... shape) {
    963                return ones(DoubleDataset.class, shape);
    964        }
    965
    966        /**
    967         * @param <T> dataset subclass
    968         * @param dataset input
    969         * @return a new dataset of same shape and class as input dataset, filled with ones
    970         */
    971        @SuppressWarnings("unchecked")
    972        public static <T extends Dataset> T ones(final T dataset) {
    973                return (T) ones(dataset, dataset.getClass());
    974        }
    975
    976        /**
    977         * @param <T> dataset sub-interface
    978         * @param clazz dataset sub-interface
    979         * @param shape output shape
    980         * @return a new dataset of given shape and class, filled with ones
    981         */
    982        @SuppressWarnings("unchecked")
    983        public static <T extends Dataset> T ones(Class<T> clazz, int... shape) {
    984                if (BooleanDataset.class.isAssignableFrom(clazz)) {
    985                        return (T) BooleanDataset.ones(shape);
    986                } else if (ByteDataset.class.isAssignableFrom(clazz)) {
    987                        return (T) ByteDataset.ones(shape);
    988                } else if (ShortDataset.class.isAssignableFrom(clazz)) {
    989                        return (T) ShortDataset.ones(shape);
    990                } else if (IntegerDataset.class.isAssignableFrom(clazz)) {
    991                        return (T) IntegerDataset.ones(shape);
    992                } else if (LongDataset.class.isAssignableFrom(clazz)) {
    993                        return (T) LongDataset.ones(shape);
    994                } else if (FloatDataset.class.isAssignableFrom(clazz)) {
    995                        return (T) FloatDataset.ones(shape);
    996                } else if (DoubleDataset.class.isAssignableFrom(clazz)) {
    997                        return (T) DoubleDataset.ones(shape);
    998                } else if (RGBByteDataset.class.isAssignableFrom(clazz)) {
    999                        return (T) new RGBByteDataset(shape).fill(1);
    1000                } else if (RGBDataset.class.isAssignableFrom(clazz)) {
    1001                        return (T) new RGBDataset(shape).fill(1);
    1002                } else if (ComplexFloatDataset.class.isAssignableFrom(clazz)) {
    1003                        return (T) ComplexFloatDataset.ones(shape);
    1004                } else if (ComplexDoubleDataset.class.isAssignableFrom(clazz)) {
    1005                        return (T) ComplexDoubleDataset.ones(shape);
    1006                } else if (StringDataset.class.isAssignableFrom(clazz)) {
    1007                        return (T) StringDataset.ones(shape);
    1008                } else if (DateDataset.class.isAssignableFrom(clazz)) {
    1009                        return (T) DateDatasetImpl.ones(shape);
    1010                } else if (ObjectDataset.class.isAssignableFrom(clazz)) {
    1011                        return (T) ObjectDataset.ones(shape);
    1012                }
    1013                throw new IllegalArgumentException("Interface not known or unsupported");
    1014        }
    1015
    1016        /**
    1017         * @param <T> dataset sub-interface
    1018         * @param itemSize item size. If equal to 1, then non-compound dataset is returned
    1019         * @param clazz dataset sub-interface
    1020         * @param shape output shape
    1021         * @return a new dataset of given item size, shape and class, filled with ones
    1022         */
    1023        @SuppressWarnings("unchecked")
    1024        public static <T extends Dataset> T ones(int itemSize, Class<T> clazz, int... shape) {
    1025                if (InterfaceUtils.isElemental(clazz)) {
    1026                        return ones(clazz, shape);
    1027                }
    1028
    1029                if (RGBByteDataset.class.isAssignableFrom(clazz)) {
    1030                        if (itemSize != 3) {
    1031                                throw new IllegalArgumentException("Number of elements not compatible with RGB type");
    1032                        }
    1033                        return (T) new RGBByteDataset(shape).fill(1);
    1034                } else if (CompoundByteDataset.class.isAssignableFrom(clazz)) {
    1035                        return (T) CompoundByteDataset.ones(itemSize, shape);
    1036                } else if (RGBDataset.class.isAssignableFrom(clazz)) {
    1037                        if (itemSize != 3) {
    1038                                throw new IllegalArgumentException("Number of elements not compatible with RGB type");
    1039                        }
    1040                        return (T) new RGBDataset(shape).fill(1);
    1041                } else if (CompoundShortDataset.class.isAssignableFrom(clazz)) {
    1042                        return (T) CompoundShortDataset.ones(itemSize, shape);
    1043                } else if (CompoundIntegerDataset.class.isAssignableFrom(clazz)) {
    1044                        return (T) CompoundIntegerDataset.ones(itemSize, shape);
    1045                } else if (CompoundLongDataset.class.isAssignableFrom(clazz)) {
    1046                        return (T) CompoundLongDataset.ones(itemSize, shape);
    1047                } else if (CompoundFloatDataset.class.isAssignableFrom(clazz)) {
    1048                        return (T) CompoundFloatDataset.ones(itemSize, shape);
    1049                } else if (CompoundDoubleDataset.class.isAssignableFrom(clazz)) {
    1050                        return (T) CompoundDoubleDataset.ones(itemSize, shape);
    1051                }
    1052                throw new IllegalArgumentException("Class not a known compound interface");
    1053        }
    1054
    1055        /**
    1056         * @param <T> dataset subclass
    1057         * @param dataset input
    1058         * @param clazz dataset class
    1059         * @return a new dataset of given class with same shape as input dataset, filled with ones
    1060         */
    1061        public static <T extends Dataset> T ones(Dataset dataset, Class<T> clazz) {
    1062                return (T) ones(dataset.getElementsPerItem(), clazz, dataset.getShapeRef());
    1063        }
    1064}