Skip to content

Commit

Permalink
Merge branch 'main' into deletion-dates
Browse files Browse the repository at this point in the history
  • Loading branch information
shapiromatron authored Jul 23, 2024
2 parents 25cd1ae + 6e04e22 commit 88699c0
Show file tree
Hide file tree
Showing 21 changed files with 165 additions and 116 deletions.
3 changes: 0 additions & 3 deletions bmds_ui/analysis/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,3 @@

class Config(AppConfig):
name = "bmds_ui.analysis"

def ready(self):
from .signals import init_command # noqa: F401
11 changes: 0 additions & 11 deletions bmds_ui/analysis/signals.py

This file was deleted.

Empty file.
31 changes: 31 additions & 0 deletions bmds_ui/desktop/sqlite3/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from sqlite3 import dbapi2 as Database

from django.db.backends.sqlite3 import base
from django.db.backends.sqlite3._functions import register as register_functions
from django.utils.asyncio import async_unsafe


class DatabaseWrapper(base.DatabaseWrapper):
# TODO - remove w/ django 5.1 release
# adapted from https://blog.pecar.me/sqlite-django-config
# https://gcollazo.com/optimal-sqlite-settings-for-django/
def _start_transaction_under_autocommit(self):
# Acquire a write lock immediately for transactions
self.cursor().execute("BEGIN IMMEDIATE")

@async_unsafe
def get_new_connection(self, conn_params):
conn = Database.connect(**conn_params)
register_functions(conn)

conn.execute("PRAGMA foreign_keys=ON")
conn.execute("PRAGMA legacy_alter_table = OFF")
conn.execute("PRAGMA journal_mode = WAL")
conn.execute("PRAGMA synchronous = NORMAL")
conn.execute("PRAGMA busy_timeout = 5000")
conn.execute("PRAGMA temp_store = MEMORY")
conn.execute("PRAGMA mmap_size = 134217728")
conn.execute("PRAGMA journal_size_limit = 67108864")
conn.execute("PRAGMA cache_size = 2000")

return conn
5 changes: 2 additions & 3 deletions bmds_ui/main/settings/desktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.getenv("BMDS_DB", APP_HOME / "pybmds.sqlite3"),
"STARTUP_OPTIONS": {"init_command": "PRAGMA journal_mode=wal;"},
"ENGINE": "bmds_ui.desktop.sqlite3",
"NAME": os.getenv("BMDS_DB", APP_HOME / "bmds-desktop.db"),
}
}

Expand Down
4 changes: 4 additions & 0 deletions bmds_ui/static/css/site.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ input[type=number] {
visibility: visible;
}

.table-fixed {
table-layout: fixed;
}

/* table column text alignment */
.col-r-1 td:nth-child(1),
.col-r-1 th:nth-child(1),
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ export const simulateClick = function(el) {
};
},
checkOrEmpty = bool => {
return <Icon name={bool ? "check2-square" : "square"} classes="bi-lg" />;
return (
<Icon
title={bool ? "checked" : "unchecked"}
name={bool ? "check2-square" : "square"}
classes="bi-lg"
/>
);
},
getLabel = function(value, mapping) {
return _.find(mapping, d => d.value == value).label;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/IndividualModel/CDFTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CDFTable extends Component {
ff(bmd_dist[1][i]),
ff(bmd_dist[0][i]),
]),
tblClasses: "table table-sm text-right col-l-1",
tblClasses: "table table-sm text-right",
};
return <Table data={data} />;
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/IndividualModel/GoodnessFit.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class GoodnessFit extends Component {
} else {
data = getContinuousNormalData(dataset, dtype, model);
}
data.tblClasses = "table table-sm text-right col-l-1";
data.tblClasses = "table table-sm text-right";
data.subheader = "Goodness of Fit";

return <Table data={data} />;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Main/Actions/Actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class Actions extends Component {
) : (
<p className="text-muted pl-4 mb-0">Please save and execute analysis.</p>
)}
{mainStore.isDesktop ? (
{mainStore.isDesktop && mainStore.canEdit ? (
<>
<div className="dropdown-divider"></div>
<span className="dropdown-header">Collections</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class DatasetModelOption extends Component {
</tr>
) : (
<tr>
<td className="text-center">{checkOrEmpty(option.enabled)}</td>
<td>{checkOrEmpty(option.enabled)}</td>
<td>{dataset.metadata.name}</td>
{option.degree !== undefined ? (
<td>{getDegreeText(dtype, option.degree)}</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ class DatasetModelOptionList extends Component {
}

return (
<table className="table table-sm">
<table className="table table-sm table-fixed">
<thead>
{dtype == Dtype.CONTINUOUS || dtype == Dtype.CONTINUOUS_INDIVIDUAL ? (
<tr className="bg-custom">
<th>Enabled</th>
<th>Dataset</th>
<th>
Maximum polynomial degree&nbsp;
Maximum Polynomial Degree&nbsp;
<HelpTextPopover content={maxDegreeText} />
</th>
<th>Adverse Direction</th>
Expand All @@ -54,7 +54,7 @@ class DatasetModelOptionList extends Component {
<th>Enabled</th>
<th>Dataset</th>
<th>
Maximum multistage degree
Maximum Multistage Degree
<HelpTextPopover content={maxDegreeText} />
</th>
</tr>
Expand Down
19 changes: 4 additions & 15 deletions frontend/src/components/Main/ModelsForm/ModelsCheckBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,41 +77,30 @@ const ModelsCheckBox = observer(props => {
<td className="text-left align-middle">Exponential</td>
<CheckBoxTd store={store} type={fr} model={"Exponential"} />
<td></td>
<CheckBoxTd store={store} type={b} model={"Exponential"} disabled={true} />
<PriorWeightTd store={store} model={"Exponential"} disabled={true} />
</tr>
<tr>
<td className="text-left align-middle">Hill</td>
<CheckBoxTd store={store} type={fr} model={"Hill"} />
<CheckBoxTd store={store} type={fu} model={"Hill"} />
<CheckBoxTd store={store} type={b} model={"Hill"} disabled={true} />
<PriorWeightTd store={store} model={"Hill"} disabled={true} />
</tr>
<tr>
<td className="text-left align-middle">Linear</td>
<td></td>
<CheckBoxTd store={store} type={fu} model={"Linear"} />
<CheckBoxTd store={store} type={b} model={"Linear"} disabled={true} />
<PriorWeightTd store={store} model={"Linear"} disabled={true} />
</tr>
<tr>
<td className="text-left align-middle">Polynomial</td>
<CheckBoxTd store={store} type={fr} model={"Polynomial"} />
<CheckBoxTd store={store} type={fu} model={"Polynomial"} />
<CheckBoxTd store={store} type={b} model={"Polynomial"} disabled={true} />
<PriorWeightTd store={store} model={"Polynomial"} disabled={true} />
</tr>
<tr>
<td className="text-left align-middle">Power</td>
<CheckBoxTd store={store} type={fr} model={"Power"} />
<CheckBoxTd store={store} type={fu} model={"Power"} />
<CheckBoxTd store={store} type={b} model={"Power"} disabled={true} />
<PriorWeightTd store={store} model={"Power"} disabled={true} />
</tr>
</tbody>
);
}
if (store.getModelType === mc.MODEL_DICHOTOMOUS) {
} else if (store.getModelType === mc.MODEL_DICHOTOMOUS) {
return (
<tbody>
<tr>
Expand Down Expand Up @@ -182,8 +171,7 @@ const ModelsCheckBox = observer(props => {
</tr>
</tbody>
);
}
if (store.getModelType === mc.MODEL_NESTED_DICHOTOMOUS) {
} else if (store.getModelType === mc.MODEL_NESTED_DICHOTOMOUS) {
return (
<tbody>
<tr>
Expand All @@ -198,8 +186,9 @@ const ModelsCheckBox = observer(props => {
</tr>
</tbody>
);
} else {
throw `Unknown modelType: ${store.getModelType}`;
}
throw `Unknown modelType: ${store.getModelType}`;
});
ModelsCheckBox.propTypes = {
store: PropTypes.any,
Expand Down
151 changes: 96 additions & 55 deletions frontend/src/components/Main/ModelsForm/ModelsCheckBoxHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,78 +5,119 @@ import React from "react";
import * as mc from "@/constants/mainConstants";
import {allModelOptions} from "@/constants/modelConstants";

import Button from "../../common/Button";
import CheckboxInput from "../../common/CheckboxInput";
import HelpTextPopover from "../../common/HelpTextPopover";
import LabelInput from "../../common/LabelInput";

const areAllModelsChecked = function(modelType, type, models) {
return type in models && models[type].length === allModelOptions[modelType][type].length;
},
SelectAllComponent = observer(props => {
const {store, type, disabled} = props;
return store.canEdit ? (
<th>
<label className="m-0">
<CheckboxInput
id={`select_all_${type}`}
disabled={disabled}
onChange={value => store.enableAll(type, value)}
checked={areAllModelsChecked(store.getModelType, type, store.models)}
/>
&nbsp;Select all
</label>
</th>
) : (
<th></th>
const {store, type, disabled, label} = props,
id = `select_all_${type}`;
return (
<>
<CheckboxInput
id={id}
disabled={disabled}
onChange={value => store.enableAll(type, value)}
checked={areAllModelsChecked(store.getModelType, type, store.models)}
/>
&nbsp;
<LabelInput label={label} htmlFor={id} />
</>
);
}),
ModelColGroup = observer(props => {
const {hasBayesianModels} = props,
cols = hasBayesianModels ? [20, 20, 20, 20, 20] : [33, 33, 34];
return (
<colgroup>
{cols.map((d, i) => (
<col key={i} width={`${d}%`} />
))}
</colgroup>
);
});

const ModelsCheckBoxHeader = observer(props => {
const {store} = props,
content = "Models were previewed in BMDS Excel 3.2 and will be formally peer reviewed.",
title = "Bayesian Model Averaging",
{hasBayesianModels} = store,
isContinuous = store.getModelType === mc.MODEL_CONTINUOUS,
isMultiTumor = store.getModelType === mc.MODEL_MULTI_TUMOR;
{canEdit} = store,
hasBayesianModels = store.getModelType === mc.MODEL_DICHOTOMOUS;
return (
<thead className="bg-custom">
<tr>
<th rowSpan="3">Models</th>
<th colSpan="2">Maximum Likelihood Estimate</th>
{hasBayesianModels ? (
<th colSpan="3" rowSpan="2">
Bayesian Model Averaging
{isContinuous ? (
<HelpTextPopover title={title} content={content}></HelpTextPopover>
<>
<ModelColGroup hasBayesianModels={hasBayesianModels} />
<thead className="bg-custom">
<tr>
<th className="align-top" rowSpan="2">
Model
{canEdit ? (
<>
<Button
className="mt-4 btn btn-sm btn-block btn-info"
onClick={store.resetModelSelection}
text="Reset Selection"
/>
</>
) : null}
</th>
) : null}
</tr>
<tr>
<th>Restricted</th>
<th>Unrestricted</th>
</tr>
<tr>
<SelectAllComponent store={store} type={"frequentist_restricted"} />
<SelectAllComponent
store={store}
type={"frequentist_unrestricted"}
disabled={isMultiTumor}
/>
{hasBayesianModels ? (
<>
<SelectAllComponent
store={store}
type={"bayesian"}
disabled={isContinuous}
/>
<th>Prior Weights</th>
</>
) : null}
</tr>
</thead>
<th colSpan="2">Maximum Likelihood Estimate</th>
{hasBayesianModels ? <th colSpan="2">Bayesian Model Averaging</th> : null}
</tr>
<tr>
<th>
Restricted
{canEdit ? (
<>
<br />
<SelectAllComponent
store={store}
type={"frequentist_restricted"}
label="Select All"
/>
</>
) : null}
</th>
<th>
Unrestricted
{canEdit ? (
<>
<br />
<SelectAllComponent
store={store}
type={"frequentist_unrestricted"}
label="Select All"
/>
</>
) : null}
</th>
{hasBayesianModels ? (
<>
<th>
Include
{canEdit ? (
<>
<br />
<SelectAllComponent
store={store}
type={"bayesian"}
label="Select All"
/>
</>
) : null}
</th>
<th>
<span className="mb-1">Prior Weight</span>
</th>
</>
) : null}
</tr>
</thead>
</>
);
});
ModelsCheckBoxHeader.propTypes = {
store: PropTypes.object,
};

export default ModelsCheckBoxHeader;
Loading

0 comments on commit 88699c0

Please sign in to comment.