Beispiel #1
0
  def get_bedcounts(self, max_ts=None, latest=False, preprocess=True):
    if isinstance(max_ts, str) and max_ts.isnumeric():
      max_ts = datetime.datetime.fromtimestamp(int(max_ts))

    result = None
    if latest:
      result = self.db.get_visible_bed_counts_for_user(
        user_id=None, force=True, max_date=max_ts
      )
    else:
      result = self.db.get_bed_counts(max_date=max_ts)

    result = store.to_pandas(result, max_depth=2)
    if result.shape[0] == 0:
      return result

    to_drop = set(result.columns).intersection([
      'icu_bed_counts', 'icu_users', 'icu_managers'
    ])
    result = result.drop(columns=to_drop)
    if preprocess:
      result = preprocessing.preprocess_bedcounts(result)

    result = result.sort_values(by=["create_date", "icu_name"])
    return result
Beispiel #2
0
 def export_icus(self) -> TextIO:
     db_cols = copy.copy(ICU_COLUMNS)
     db_cols.remove('region')
     icus_pd = store.to_pandas(self._store.get_icus(), max_depth=1)
     out_pd = icus_pd[db_cols].copy()
     out_pd['region'] = icus_pd['region_name']
     out_pd = out_pd[ICU_COLUMNS]
     return out_pd.to_csv(index=False)
Beispiel #3
0
 async def generate_plots(self):
     db = self.db_factory.create()
     df_bedcounts = to_pandas(db.get_bed_counts())
     df_bedcounts = normalize_colum_names(df_bedcounts)
     logging.info(
         '[periodic callback] Starting plots generation with predicu')
     cached_data = {'bedcounts': df_bedcounts}
     generate_plots(cached_data=cached_data,
                    output_dir=self.config.backoffice.extra_plots_dir)
    def get(self):
        """Serves a page with a table gathering current bedcount data with some extra information."""
        arg_region = self.get_query_argument('region', default=None)
        locale = self.get_user_locale()

        current_region = None
        current_region_name = locale.translate("All regions")
        if arg_region is not None and arg_region.isdigit():
            try:
                current_region = self.db.get_region(int(arg_region))
                current_region_name = current_region.name
            except Exception:
                logging.warning(f"Invalid query argument: region={arg_region} "
                                f"Falling back to all regions.")

        figures = []

        bed_counts = self.db.get_visible_bed_counts_for_user(
            self.current_user.user_id)
        if bed_counts:
            bed_counts = to_pandas(bed_counts)
        else:
            # when no data, make sure the resulting dataframe has
            # correct column names.
            columns = [key for key in dir(BedCount) if not key.startswith('_')]
            columns += ['icu_dept']
            bed_counts = pd.DataFrame([], columns=columns)

        if current_region is not None:
            mask = bed_counts['icu_region_id'] == current_region.region_id
            bed_counts = bed_counts[mask]

        df, metrics_layout = _prepare_data(bed_counts)

        p = _make_bar_plot(df, locale)

        script, div = components(p)
        figures.append(dict(script=script, div=div))

        plots_extra = _list_extra_plots(
            Path(self.config.backoffice.extra_plots_dir))
        # stack two columns per row
        plots_extra = _grouper(plots_extra, 2)

        regions = [{
            'name': el.name,
            'id': el.region_id
        } for el in self.db.get_regions()]
        regions = list(sorted(regions, key=lambda x: x['name']))

        return self.render("operational-dashboard.html",
                           figures=figures,
                           regions=regions,
                           current_region_name=current_region_name,
                           metrics_layout=metrics_layout,
                           plots_extra=plots_extra)
Beispiel #5
0
  def get(self, collection='bedcounts', max_ts=None, preprocess=None):
    """Returns the proper pandas dataframe."""
    if collection in ['bedcounts', 'all_bedcounts']:
      latest = collection == 'bedcounts'
      preprocess = not latest if preprocess is None else preprocess
      return self.get_bedcounts(max_ts, latest=latest, preprocess=preprocess)

    if collection == 'icus':
      result = self.db.get_icus()
    else:
      result = self.db.get_regions()
    return store.to_pandas(result, max_depth=0)
Beispiel #6
0
def test_integration_generate_plots(name, integration_config, tmpdir):
    store = db_store.create_store_factory_for_sqlite_db(
        integration_config).create()

    cached_data = load_test_data()
    cached_data['bedcounts'] = to_pandas(store.get_bed_counts())

    output_dir = str(tmpdir.mkdir("sub"))
    generate_plots(plots=[name],
                   output_dir=output_dir,
                   cached_data=cached_data)
    assert (Path(output_dir) / (name + ".png")).exists()
Beispiel #7
0
  def get(self, collection):
    file_format = self.get_query_argument('format', default=None)
    max_ts = self.get_query_argument('max_ts', default=None)
    data = None

    get_fn = self.get_fns.get(collection, None)
    if get_fn is None:
      logging.debug("API called with incorrect endpoint: {collection}.")
      self.redirect(home.HomeHandler.ROUTE)
      return

    if collection in ['bedcounts', 'all_bedcounts']:
      if isinstance(max_ts, str) and max_ts.isnumeric():
        max_ts = datetime.datetime.fromtimestamp(int(max_ts))
      get_fn = functools.partial(get_fn, max_date=max_ts)
      data = store.to_pandas(get_fn(), max_depth=1)
    else:
      data = store.to_pandas(get_fn(), max_depth=0)

    for k, v in _get_headers(collection, file_format).items():
      self.set_header(k, v)

    if file_format == 'csv':
      stream = io.StringIO()
      data.to_csv(stream, index=False)
      self.write(stream.getvalue())
    elif file_format == 'hdf':
      with tempfile.NamedTemporaryFile() as f:
        tmp_path = f.name
      data.to_hdf(
        tmp_path,
        key='data',
        complib='blosc:lz4',
        complevel=9,
      )
      with open(tmp_path, 'rb') as f:
        self.write(f.read())
      os.remove(tmp_path)
    else:
      self.write(data.to_html())
    def get(self):
        """Serves a page with a table gathering current bedcount data with some extra information."""
        arg_region = self.get_query_argument('region', default=None)

        current_region = None
        current_region_name = "Toutes les régions"
        if arg_region is not None and arg_region.isdigit():
            try:
                current_region = self.db.get_region(int(arg_region))
                current_region_name = current_region.name
            except Exception:
                logging.warning(f"Invalid query argument: region={arg_region} "
                                f"Falling back to all regions.")

        figures = []

        bed_counts = self.db.get_visible_bed_counts_for_user(self.user.user_id)

        bed_counts = to_pandas(bed_counts)

        if current_region is not None:
            mask = bed_counts['icu_region_id'] == current_region.region_id
            bed_counts = bed_counts[mask]

        df, metrics_layout = _prepare_data(bed_counts)

        p = _make_bar_plot(df)

        script, div = components(p)
        figures.append(dict(script=script, div=div))

        plots_extra = _list_extra_plots(
            Path(self.config.backoffice.extra_plots_dir))
        # stack two columns per row
        plots_extra = _grouper(plots_extra, 2)

        regions = [{
            'name': el.name,
            'id': el.region_id
        } for el in self.db.get_regions()]
        regions = list(sorted(regions, key=lambda x: x['name']))

        return self.render("operational-dashboard.html",
                           figures=figures,
                           regions=regions,
                           current_region_name=current_region_name,
                           metrics_layout=metrics_layout,
                           plots_extra=plots_extra)
Beispiel #9
0
def test_load_test_data():
    """Ensure consitency between test data used in plots and BD schema
  
  e.g. between load_test_data and db.get_bed_counts
  """
    # TODO: cache generation of in memory DB with fake data into a pytest fixture
    df = load_test_data()['bedcounts']

    # duplicate columns with "date"
    del df['datetime']

    store = StoreFactory(create_engine("sqlite:///:memory:")).create()
    populate_store_fake(store)
    df_db = to_pandas(store.get_bed_counts())
    df_db = normalize_colum_names(df_db, 'bedcounts')
    # All bedcount columns in tests data used for plots must belong to the DB schema
    missing_columns = set(df.columns).difference(df_db.columns)
    assert not missing_columns
Beispiel #10
0
  def get(self, collection):
    if self.current_user.access_type not in self.GET_ACCESS:
      logging.error(
        f"API called with incorrect access_type: {self.current_user.access_type}."
      )
      self.set_status(403)
      return

    file_format = self.get_query_argument('format', default=None)
    max_ts = self.get_query_argument('max_ts', default=None)
    # should_preprocess: whether preprocessing should be applied to the data
    # the raw data of ICUBAM contains inputs errors and this preprocessing will
    # attempt to fix them
    # it should be used cautiously because it alters the data in ways that are
    # useful for analysis purposes but not necessarily reflect the exact/real
    # bed count values
    # whenever a query argument named 'preprocess' is present, we enable this
    # preprocessing (it can be 'preprocess=<anything>' or simply 'preprocess')
    should_preprocess = (
      self.get_query_argument('preprocess', default=None) is not None
    )
    data = None

    get_fn = self.get_fns.get(collection, None)
    if get_fn is None:
      logging.debug("API called with incorrect endpoint: {collection}.")
      self.redirect(home.HomeHandler.ROUTE)
      return

    if collection in ['bedcounts', 'all_bedcounts']:
      if isinstance(max_ts, str) and max_ts.isnumeric():
        max_ts = datetime.fromtimestamp(int(max_ts))
      get_fn = functools.partial(get_fn, max_date=max_ts)
      data = store.to_pandas(get_fn(), max_depth=1)
      if collection == 'all_bedcounts' and should_preprocess:
        # this cached_data dict is just a way to tell predicu not to load the
        # data from ICUBAM and use this already loaded data instead
        cached_data = {'raw_icubam': data}
        data = predicu.data.load_bedcounts(
          cached_data=cached_data,
          clean=True,
        )
    else:
      data = store.to_pandas(get_fn(), max_depth=0)

    for k, v in _get_headers(collection, file_format).items():
      self.set_header(k, v)

    if file_format == 'csv':
      stream = io.StringIO()
      data.to_csv(stream, index=False)
      self.write(stream.getvalue())
    elif file_format == 'hdf':
      with tempfile.NamedTemporaryFile() as f:
        tmp_path = f.name
      data.to_hdf(
        tmp_path,
        key='data',
        complib='blosc:lz4',
        complevel=9,
      )
      with open(tmp_path, 'rb') as f:
        self.write(f.read())
      os.remove(tmp_path)
    else:
      self.write(data.to_html())
Beispiel #11
0
def make(user_id,
         db,
         region=None,
         locale=None,
         extra_plots_dir="",
         external=False):
    current_region = None
    if locale is not None:
        current_region_name = locale.translate("All regions")
    else:
        current_region_name = "All regions"
    current_region_id = None

    if region is not None and region.isdigit():
        try:
            current_region = db.get_region(int(region))
            current_region_name = current_region.name
            current_region_id = int(region)
        except Exception:
            logging.warning(f"Invalid query argument: region={region} "
                            f"Falling back to all regions.")

    if not external:
        get_counts_fn = db.get_visible_bed_counts_for_user
    else:
        get_counts_fn = functools.partial(
            db.get_bed_counts_for_external_client, latest=True)

    figures = []
    bed_counts = get_counts_fn(user_id)
    if bed_counts:
        bed_counts = to_pandas(bed_counts)
        region_id_seen = bed_counts.icu_region_id.unique().tolist()
        if current_region is not None:
            mask = bed_counts['icu_region_id'] == current_region.region_id
            bed_counts = bed_counts[mask]
    else:
        # when no data, make sure the resulting dataframe has
        # correct column names.
        columns = [key for key in dir(BedCount) if not key.startswith('_')]
        columns += ['icu_dept']
        bed_counts = pd.DataFrame([], columns=columns)
        region_id_seen = []

    df, metrics_layout = _prepare_data(bed_counts)

    p = _make_bar_plot(df, locale)

    script, div = components(p)
    figures.append(dict(script=script, div=div))

    plots_extra = _list_extra_plots(Path(extra_plots_dir))

    img_map = ImageURLMapper(plots_extra)

    regions = [{
        'name': el.name,
        'id': el.region_id
    } for el in db.get_regions() if el.region_id in region_id_seen]
    regions = list(sorted(regions, key=lambda x: x['name']))

    return {
        'figures': figures,
        'regions': regions,
        'region_name': current_region_name,
        'region_id': current_region_id,
        'metrics_layout': metrics_layout,
        'img_map': img_map,
        '_grouper': _grouper,
    }