-
Notifications
You must be signed in to change notification settings - Fork 1
/
app.py
144 lines (113 loc) · 4.78 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# Copyright (c) 2022, Colas Droin. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
""" In this module, the app is instantiated with a given server and cache config. Three global
variables shared across all user sessions are also instantiated: data, atlas and figures.
"""
# ==================================================================================================
# --- Imports
# ==================================================================================================
# Standard modules
import dash
import dash_bootstrap_components as dbc
from dash.long_callback import DiskcacheLongCallbackManager
import flask
from flask_caching import Cache
import logging
from uuid import uuid4
import diskcache
import os
from modules.scRNAseq import ScRNAseq
# LBAE modules
from modules.tools.misc import logmem
logging.info("Memory use before any LBAE import" + logmem())
from modules.maldi_data import MaldiData
logging.info("Memory use after MaldiData import" + logmem())
from modules.figures import Figures
logging.info("Memory use after Figures import" + logmem())
from modules.atlas import Atlas
from modules.launch import Launch
from modules.storage import Storage
from modules.scRNAseq import ScRNAseq
# ==================================================================================================
# --- App pre-computations
# ==================================================================================================
logging.info("Memory use before any global variable declaration" + logmem())
# Define if the app will use only a sample of the dataset, and uses a lower resolution for the atlas
SAMPLE_DATA = False
# Define paths for the sample/not sample data
if SAMPLE_DATA:
path_data = "data_sample/whole_dataset/"
path_annotations = "data_sample/annotations/"
path_db = "data_sample/app_data/data.db"
cache_dir = "data_sample/cache/"
else:
path_data = "data/whole_dataset/"
path_annotations = "data/annotations/"
path_db = "data/app_data/data.db"
cache_dir = "data/cache/"
# Load shelve database
storage = Storage(path_db)
# Load data
data = MaldiData(path_data, path_annotations, sample_data=SAMPLE_DATA)
# If True, only a small portions of the figures are precomputed (if precomputation has not already
# been done). Used for debugging purposes.
sample = False
# Load Atlas and Figures objects. At first launch, many objects will be precomputed and shelved in
# the classes Atlas and Figures.
atlas = Atlas(data, storage, resolution=25, sample=sample)
scRNAseq = ScRNAseq()
figures = Figures(data, storage, atlas, scRNAseq, sample=sample)
logging.info("Memory use after three main object have been instantiated" + logmem())
# Compute and shelve potentially missing objects
launch = Launch(data, atlas, figures, storage)
# This line can be commented out to gain speed at startup... But lose security and speed during use
launch.launch()
logging.info("Memory use after main functions have been compiled" + logmem())
# ==================================================================================================
# --- Instantiate app and caching
# ==================================================================================================
# Launch server
server = flask.Flask(__name__)
# Prepare long callback support
launch_uid = uuid4()
cache_long_callback = diskcache.Cache(cache_dir)
long_callback_manager = DiskcacheLongCallbackManager(
cache_long_callback,
cache_by=[lambda: launch_uid],
expire=500,
)
# Instantiate app
app = dash.Dash(
title="Lipids Brain Atlas Explorer",
external_stylesheets=[dbc.themes.DARKLY],
external_scripts=[
{"src": "https://cdn.jsdelivr.net/npm/[email protected]/dist/dom-to-image.min.js"}
],
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
server=server,
suppress_callback_exceptions=False,
long_callback_manager=long_callback_manager,
compress=True,
)
# Add a class attribute to specify if redis is being used
app.use_redis = False
# Set up flask caching in addition to long_callback_manager
if app.use_redis:
CACHE_CONFIG = {
# We use 'redis' for faster file retrieval
"CACHE_TYPE": "redis",
"CACHE_REDIS_URL": os.environ.get("REDIS_URL", "redis://localhost:6379"),
}
else:
CACHE_CONFIG = {
# We use 'FileSystemCache' as we want the application to be lightweight in term of RAM
"CACHE_TYPE": "FileSystemCache",
"CACHE_DIR": cache_dir,
"CACHE_THRESHOLD": 200,
}
# Initiate Cache
cache_flask = Cache()
cache_flask.init_app(app.server, config=CACHE_CONFIG) # Comment this line for a faster launch
# Initiate the cache as unlocked
cache_flask.set("locked-cleaning", False)
cache_flask.set("locked-reading", False)