Code Monkey home page Code Monkey logo

omero-cli-zarr's Introduction

OMERO CLI Zarr plugin

This OMERO command-line plugin allows you to export Images and Plates from OMERO as zarr files, according to the spec at https://github.com/ome/omero-ms-zarr/blob/master/spec.md as well as Masks associated with Images.

Images are 5D arrays of shape (t, c, z, y, x). Plates are a hierarchy of plate/row/column/field(image). Masks are 2D bitmasks which can exist on muliplte planes of an Image. In ome-zarr sets of Masks are collected together into "labels".

It supports export using 2 alternative methods:

  • By default the OMERO API is used to load planes as numpy arrays and the zarr file is created from this data. NB: currently, large tiled images are not supported by this method.
  • Alternatively, if you can read directly from the OMERO binary repository and have installed https://github.com/glencoesoftware/bioformats2raw then you can use this to create zarr files.

Usage

Images and Plates

To export Images or Plates via the OMERO API:

# Image will be saved in current directory as 1.zarr
$ omero zarr export Image:1

# Plate will be saved in current directory as 2.zarr
$ omero zarr export Plate:2

# Specify an output directory
$ omero zarr --output /home/user/zarr_files export Image:1

# By default, a tile size of 1024 is used. Specify values with
$ omero zarr export Image:1 --tile_width 256 --tile_height 256

NB: If the connection to OMERO is lost and the Image is partially exported, re-running the command will attempt to complete the export.

To export images via bioformats2raw we use the `--bf` flag:

export MANAGED_REPO=/var/omero/data/ManagedRepository
export BF2RAW=/opt/tools/bioformats2raw-0.2.0-SNAPSHOT

$ omero zarr --output /home/user/zarr_files export 1 --bf
Image exported to /home/user/zarr_files/2chZT.lsm

Masks and Polygons

To export Masks or Polygons for an Image or Plate, use the masks or polygons command:

# Saved under 1.zarr/labels/0 - 1.zarr/ must already exist
$ omero zarr masks Image:1

# Labels saved under each image. e.g 2.zarr/A/1/0/labels/0
# Plate should already be exported
$ omero zarr masks Plate:2

# Saved under zarr_files/1.zarr/labels/0
$ omero zarr --output /home/user/zarr_files masks Image:1

# Specify the label-name. (default is '0')
# e.g. Export to 1.zarr/labels/A
$ omero zarr masks Image:1 --label-name=A

# Allow overlapping masks or polygons (overlap will be maximum value of the dtype)
$ omero zarr polygons Image:1 --overlaps=dtype_max

The default behaviour is to export all masks or polygons on the Image to a single 5D "labeled" zarr array, with a different value for each Shape. An exception will be thrown if any of the masks overlap, unless the --overlaps option is used as above.

An alternative to handle overlapping masks is to split masks into non-overlapping zarr groups using a "label-map" which is a csv file that specifies the name of the zarr group for each ROI on the Image. Columns are ID, NAME, ROI_ID.

For example, to create a group from the textValue of each Shape, you can use this command:

omero hql --style=plain "select distinct s.textValue, s.roi.id from Shape s where s.roi.image.id = 5514375" --limit=-1 | tee 5514375.rois

This creates a file 5514375.rois like this:

0,Cell,1369132
1,Cell,1369134
2,Cell,1369136
...
40,Chromosomes,1369131
41,Chromosomes,1369133
42,Chromosomes,1369135
...

This will create zarr groups of Cell and Chromosomes under 5514375.zarr/labels/:

$ omero zarr masks Image:5514375 --label-map=5514375.rois

License

This project, similar to many Open Microscopy Environment (OME) projects, is licensed under the terms of the GNU General Public License (GPL) v2 or later.

Copyright

2020-2023, The Open Microscopy Environment

omero-cli-zarr's People

Contributors

dominikl avatar jburel avatar joshmoore avatar manics avatar pre-commit-ci[bot] avatar sbesson avatar will-moore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

omero-cli-zarr's Issues

Standardize _creator field

Currently,

(z) /opt/omero-ms-zarr $cat 101.zarr/.zattrs
{
    "_creator": {
        "name": "omero-zarr",
        "version": "0.0.2.dev79+gb361c09"
    },

is added on export. We may want to slightly update this to match with a vocabulary like Dublin Core or W3C PROV.

Masks with Z or T null should apply across all Z or T indices

See #82 (comment)

Currently, if all masks have no Z or T index, the omero zarr masks Image:ID exports a label data block with size-Z or size-T = 1. However, this relies on all other clients to interpret this in the same way that OMERO does (to display that label image across all Z/T indices).
Instead, it it better to export a better representation of how we want the data to appear. If a Mask should apply across all Z or T planes, then we should export a Label that spans all those Z/T planes.

cc @pwalczysko

export bioformats2raw.layout for Fileset or Images

See ome/ngff#112 (comment)

The bioformats2raw.layout could be generated from a Fileset or from a list of Image IDs.

In the case of a Fileset, we can get Image IDs with fileset.copyImages().

With a list of Image IDs, we can export each individual OME-NGFF under paths 0/, 1/ etc and manually generate
OME-XML according to https://docs.openmicroscopy.org/ome-model/6.2.2/specifications/minimum.html (with <MetadataOnly/>) for each Image.
I don't see a way to get export this OME-XML automatically from OMERO for a Fileset. But also, it would be handy to generate bioformats2raw.layout collection of Images that are NOT a Fileset, which should be possible with this approach.

I imagine the cli could look like:

$ omero export Fileset:1
$ omero export Image:1,2,3

Going to start looking into this...
cc @sbesson @joshmoore

Add support for HCS export with the `--bf` flag

See IDR/idr-zarr-tools#1 for the original discussion.

While driving the export of IDR datasets, some wrapper scripts have been written on top of bioformat2raw 0.2.x to handle the bioformats2raw Zarr group layout and only retain the OME-Zarr image and add the OMERO metadata.

In the case of non-HCS data, #75 should have migrated all this logic at the level of this plugin using the command:

omero zarr export --bf Image:xxx

Support for HCS data export as OME-Zarr is the last part to be added. The --bf flag now requires bioformat2raw 0.3.0 which brings native support for HCS support and existing code can be re-used to add omero metadata to each well sample.

Probably the main point of review will be to ensure that the layouts are compatible . ome zarr export Plate:xxx uses the plate/well/row/field of view layout as described in https://ngff.openmicroscopy.org/0.1/ while bioformat2raw retains a flat layout where each field of view is 0-based index for compatibility with METADATA.ome.xml and raw2ometiff. My expectation is that both layouts should be equivalent as long as the correct metadata is filled but this will be a good occasion to compare and test via different downstream clients.

Use `clientPath` if available

Similar to searching /OMERO/ManagedRepository, omero-cli-zarr could be told to search the clientPath location for in-place imported files.

Note: this is currently what's happening in https://github.com/IDR/SubmissionWorkflow/pull/7, e.g. HQL to select image IDs and paths:

+omero hql -q --all --style=plain "select i.id, fe.clientPath from Project p join p.datasetLinks pdl join pdl.child d join d.imageLinks dil join dil.child i join i.fileset f join f.usedFiles fe where p.name like 'idr0062%' | cut -f1 -d,"
+6001237,uod/idr/filesets/idr0062-blin-nuclearsegmentation/20190429-ftp/Acini/E14tg2a_d2.tif,idr0062-blin-nuclearsegmentation/experimentA
+6001238,uod/idr/filesets/idr0062-blin-nuclearsegmentation/20190429-ftp/Acini/Tcf_Het_d2.tif,idr0062-blin-nuclearsegmentation/experimentA
+6001239,uod/idr/filesets/idr0062-blin-nuclearsegmentation/20190429-ftp/Acini/Tcf15_KO_d2.tif,idr0062-blin-nuclearsegmentation/experimentA
...

Update docs README

The README says you can use --output but trying seems to suggest not.
Also need to rename 'masks' to 'labels' in the README (and elsewhere?)

$ omero zarr export Image:139615 --output /Users/wmoore/Desktop/ZARR/data/
/Users/wmoore/opt/miniconda3/envs/omero zarr export: error: unrecognized arguments: --output /Users/wmoore/Desktop/ZARR/data/

Append type to export value

Now that zarr export Plate:1 and zarr export Image:1 are both valid, we may want to make the target directory more explicit. This may also influence the spec.md naming.

ModuleNotFoundError: No module named 'omero_zarr._version'

I'm seeing an import Error using a conda environment on ome-zarr-dev1 machine (but I don't see any error on a local env): e.g.

(omero_zarr_export) [wmoore@ome-zarr-dev1 idr0001]$ omero login
Error loading: /lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/omero/plugins/zarr.py
Traceback (most recent call last):
  File "/lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/omero/cli.py", line 1690, in loadpath
    execfile(str(pathobj), loc)
  File "/lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/past/builtins/misc.py", line 87, in execfile
    exec_(code, myglobals, mylocals)
  File "/lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/omero/plugins/zarr.py", line 1, in <module>
    from omero_zarr.cli import HELP, ZarrControl
  File "/lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/omero_zarr/__init__.py", line 21, in <module>
    from ._version import version as __version__
ModuleNotFoundError: No module named 'omero_zarr._version'

I tried a different pattern to import __version__ within __init__.py:

from . import _version

__version__ = _version.version

Again, this works on my local machine but not on the ome-zarr-dev1 server env:

(omero_zarr_export) [wmoore@ome-zarr-dev1 ~]$ python
Python 3.9.0 | packaged by conda-forge | (default, Nov 26 2020, 07:57:39) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from omero_zarr.cli import HELP, ZarrControl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/omero_zarr/__init__.py", line 21, in <module>
    from . import _version
ImportError: cannot import name '_version' from partially initialized module 'omero_zarr' (most likely due to a circular import) (/lifesci/groups/jrs/wmoore/miniconda3/envs/omero_zarr_export/lib/python3.9/site-packages/omero_zarr/__init__.py)

Plate export improvements

Comments from now closed PR #28

@joshmoore
Feedback from ome/ome-zarr-py#56 :
The contents of the Field_* folder should probably be multiscales. That adds yet another layer to this already pretty deep hierarchy, but it will mean we can always assume a pyramid.
Several of the string elements in the path aren't readably computable at the moment (see https://github.com/ome/ome-zarr-py/pull/56/files#diff-b50d9715cc6e4017cfc055fd0ed73ecb5d9158e17f4d58ca5b3ba08b89c46657R354-R358) Ideas on this front are:
- encode the naming scheme for row and column
- encode an array of these values rather than the row/column size
- encode the paths to the individual images
is probably the easiest for the moment. 3. is more verbose but is probably my long-term preference.

@sbesson
"The contents of the Field_* folder should probably be multiscales. That adds yet another layer to this already pretty deep hierarchy, but it will mean we can always assume a pyramid."
Also assuming multiscales gets increasingly used for thumbnailing, big ๐Ÿ‘ for having this a MUST rather than a SHOULD in the spec from my side.

`zarr export` doesn't support big images

(omero) /opt/data $omero zarr export Image:9798462
Using session for [email protected]:4064. Idle timeout: 10 min. Current group: Public
Exporting to 9798462.zarr (0.4)
WARNING:omero.gateway:UnknownLocalException on <class 'omero.gateway.OmeroGatewaySafeCallWrapper'> to <66327e22-3b85-4676-96a2-5d68a03e256comero.api.RawPixelsStore> getPlane((0, 0, 0), {})
Traceback (most recent call last):
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 4853, in __call__
    return self.f(*args, **kwargs)
  File "/opt/omero-py/target/omero_api_RawPixelsStore_ice.py", line 1199, in getPlane
    return _M_omero.api.RawPixelsStore._op_getPlane.invoke(self, ((z, c, t), _ctx))
Ice.UnknownLocalException: exception ::Ice::UnknownLocalException
{
    unknown = ConnectionI.cpp:1573: Ice::MemoryLimitException:
protocol error: memory limit exceeded:
requested 346982825 bytes, maximum allowed is 256000000 bytes (see Ice.MessageSizeMax)
}
ERROR:omero.gateway:Failed to getPlane() or getTile() from rawPixelsStore
Traceback (most recent call last):
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 7526, in getTiles
    rawPlane = rawPixelsStore.getPlane(z, c, t)
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 4856, in __call__
    return self.handle_exception(e, *args, **kwargs)
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 4853, in __call__
    return self.f(*args, **kwargs)
  File "/opt/omero-py/target/omero_api_RawPixelsStore_ice.py", line 1199, in getPlane
    return _M_omero.api.RawPixelsStore._op_getPlane.invoke(self, ((z, c, t), _ctx))
Ice.UnknownLocalException: exception ::Ice::UnknownLocalException
{
    unknown = ConnectionI.cpp:1573: Ice::MemoryLimitException:
protocol error: memory limit exceeded:
requested 346982825 bytes, maximum allowed is 256000000 bytes (see Ice.MessageSizeMax)
}
Traceback (most recent call last):
  File "/usr/local/anaconda3/envs/omero/bin/omero", line 11, in <module>
    load_entry_point('omero-py', 'console_scripts', 'omero')()
  File "/opt/omero-py/target/omero/main.py", line 125, in main
    rv = omero.cli.argv()
  File "/opt/omero-py/target/omero/cli.py", line 1784, in argv
    cli.invoke(args[1:])
  File "/opt/omero-py/target/omero/cli.py", line 1222, in invoke
    stop = self.onecmd(line, previous_args)
  File "/opt/omero-py/target/omero/cli.py", line 1299, in onecmd
    self.execute(line, previous_args)
  File "/opt/omero-py/target/omero/cli.py", line 1381, in execute
    args.func(args)
  File "/usr/local/anaconda3/envs/omero/lib/python3.7/site-packages/omero_zarr/cli.py", line 65, in _wrapper
    return func(self, *args, **kwargs)
  File "/usr/local/anaconda3/envs/omero/lib/python3.7/site-packages/omero_zarr/cli.py", line 265, in export
    image_to_zarr(image, args)
  File "/usr/local/anaconda3/envs/omero/lib/python3.7/site-packages/omero_zarr/raw_pixels.py", line 32, in image_to_zarr
    add_image(image, root, cache_dir=cache_dir)
  File "/usr/local/anaconda3/envs/omero/lib/python3.7/site-packages/omero_zarr/raw_pixels.py", line 95, in add_image
    cache_file_name_func=get_cache_filename,
  File "/usr/local/anaconda3/envs/omero/lib/python3.7/site-packages/omero_zarr/raw_pixels.py", line 155, in add_raw_image
    plane = next(planes)
  File "/usr/local/anaconda3/envs/omero/lib/python3.7/site-packages/omero_zarr/raw_pixels.py", line 74, in planeGen
    yield from planes
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 7559, in getTiles
    raise exc
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 7526, in getTiles
    rawPlane = rawPixelsStore.getPlane(z, c, t)
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 4856, in __call__
    return self.handle_exception(e, *args, **kwargs)
  File "/opt/omero-py/target/omero/gateway/__init__.py", line 4853, in __call__
    return self.f(*args, **kwargs)
  File "/opt/omero-py/target/omero_api_RawPixelsStore_ice.py", line 1199, in getPlane
    return _M_omero.api.RawPixelsStore._op_getPlane.invoke(self, ((z, c, t), _ctx))
Ice.UnknownLocalException: exception ::Ice::UnknownLocalException
{
    unknown = ConnectionI.cpp:1573: Ice::MemoryLimitException:
protocol error: memory limit exceeded:
requested 346982825 bytes, maximum allowed is 256000000 bytes (see Ice.MessageSizeMax)
}

Improve reporting the "export image" error

When I export an image using a specific id for the first time, it works fine:
omero zarr export Image:xx

But if I try to export it again using the same id, I get the error message at the end of this issue description.

Will mentioned that this is expected as Zarr won't overwrite the existing data that the user creates with the first export. The user can either delete before repeating or output to a different directory.

I think we need a more user-friendly message to inform the user explicitly about this rather than throwing an exception.

Traceback (most recent call last):
File "/home/khaled/anaconda3/envs/ome_ngff/bin/omero", line 8, in
sys.exit(main())
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero/main.py", line 125, in main
rv = omero.cli.argv()
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero/cli.py", line 1784, in argv
cli.invoke(args[1:])
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero/cli.py", line 1222, in invoke
stop = self.onecmd(line, previous_args)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero/cli.py", line 1299, in onecmd
self.execute(line, previous_args)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero/cli.py", line 1381, in execute
args.func(args)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero_zarr/cli.py", line 65, in _wrapper
return func(self, *args, **kwargs)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero_zarr/cli.py", line 260, in export
image_to_zarr(image, args)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero_zarr/raw_pixels.py", line 27, in image_to_zarr
n_levels, axes = add_image(image, root, cache_dir=cache_dir)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero_zarr/raw_pixels.py", line 82, in add_image
return add_raw_image(
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/omero_zarr/raw_pixels.py", line 155, in add_raw_image
parent.create(
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/zarr/hierarchy.py", line 891, in create
return self._write_op(self._create_nosync, name, **kwargs)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/zarr/hierarchy.py", line 661, in _write_op
return f(*args, **kwargs)
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/zarr/hierarchy.py", line 897, in _create_nosync
return create(store=self._store, path=path, chunk_store=self._chunk_store,
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/zarr/creation.py", line 138, in create
init_array(store, shape=shape, chunks=chunks, dtype=dtype, compressor=compressor,
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/zarr/storage.py", line 353, in init_array
_init_array_metadata(store, shape=shape, chunks=chunks, dtype=dtype,
File "/home/khaled/anaconda3/envs/ome_ngff/lib/python3.9/site-packages/zarr/storage.py", line 384, in _init_array_metadata
raise ContainsArrayError(path)
zarr.errors.ContainsArrayError: path '0' contains an array

bioformats2raw 0.5.0 upgrade and specification compatibility

omero zarr export can write OME-NGFF from OMERO images using either bioformats2raw or ome-zarr-py depending on whether the --bf flag is passed.

As of the 0.3.0 release, omero-cli-zarr will write OME-NGFF according to the 0.4 specification when using ome-zarr-py and according to the 0.2 specification when using the current stable release of bioformats2raw 0.4.0.

From the bioformats2raw front, the upcoming 0.5.0 release should add support for writing OME-NGFF 0.4 specification - see https://github.com/orgs/glencoesoftware/projects/11. As soon as a release candidate/full release is available, a first action should be to test this workflow and confirm the data is written as expected.

A related question is whether we should enforce a dependency on the version of bioformats2raw so that the tool writes the datasets using the same version of the OME-NGFF specification independently of the passed flag. This is not something that can be defined at the Python packaging metadata level as bioformats2raw needs to be installed separately and is rather installed separately as a Java runtime dependency.

One simple approach would be to check for the return value of bioformatsraw --version. Alternatively, we might want to look into an API and possible a command-line option allowing to return the version of the OME-NGFF specification written by bioformats2raw ?

/cc @melissalinkert

Installation instructions

See #123 (comment)

Naively installing in a clean env...

conda create -n myenv python=3.8
conda activate myenv
pip install omero-cli-zarr

...
ERROR: Failed building wheel for zeroc-ice
...
error: legacy-install-failure

ร— Encountered error while trying to install package.
โ•ฐโ”€> zeroc-ice

Need to tell users to install omero-py first (as described on omero-py README)

cc @pwalczysko

Review export command-line options

I could imagine having a method for setting arbitrary bioformats2raw properties:

--bf:max_workers=

Originally posted by @joshmoore in #76 (comment)

Could even go as far as --bf2raw-config=<config_file> with an INI style of YAML list of key/value pairs to be passed to bioformats2raw

Originally posted by @sbesson in #76 (comment)

well, if you're going to go that far, I'd take a config file for all of the properties here, and separate into [bioformats2raw] and [default] (or [omero]) ;)

Originally posted by @joshmoore in #76 (comment)

Formalize/extend colors

Currently colors are a simple RGBA integer. There are any number of options/models that could be implemented, though we need to watch out for over-complexity.

Calculate best mask dtype from max label-value

Currently, the default label_bits is set to 64, which is much higher than is needed in many cases.
We could calculate a more suitable value from the highest label-value we need to store.

 masks.add_argument(
            "--label-bits",
            default=str(max(MASK_DTYPE_SIZE.keys())),
            choices=[str(s) for s in sorted(MASK_DTYPE_SIZE.keys())],
            help=(
                "Integer bit size for each label pixel, use 1 for a binary "
                "label, default %(default)s"
            ),
        )
MASK_DTYPE_SIZE: Dict[int, np.dtype] = {
    1: np.bool,
    8: np.int8,
    16: np.int16,
    32: np.int32,
    64: np.int64,
}

cc @joshmoore

Replace print statements with logging

          I tried the example at https://docs.python.org/3/howto/logging.html#changing-the-format-of-displayed-messages

adding this at the top of cli.py

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')

but that only printed:

WARNING:root:And this, too

So it looks like something else is calling logging.basicConfig before me, so that my call above is then ignored?

Agreed that we could look to remove print statements in a different PR, since this one is already quite long, and print is used elsewhere already.

Originally posted by @will-moore in #134 (comment)

labels exported as dtype i8

Labels are exported with zarr arrays of dypte i8

labels = np.zeros(mask_shape, np.int64)

And it's the default option at

default=str(max(MASK_DTYPE_SIZE.keys())),

If you try to view these in the web e.g. vizarr
https://hms-dbmi.github.io/vizarr/?source=https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001247.zarr/labels/0
or https://ome-ngff-validator.netlify.app/?source=https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001247.zarr/labels/0
this fails due to zarr.js not supporting i8 (and it doesn't look like it's going to anytime soon):
gzuidhof/zarr.js#85

To quote @manzt "If you have control over the data you are generating, I would recommend thinking about whether you really require the entire range of integers that 64-bit integer offers. If you can avoid using them, you will have an easier time in your web-application and the size of data transferred to your application will be much smaller".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.