Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore OMR search frontend #893

Merged
merged 10 commits into from
Aug 15, 2024
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,17 @@ The user will be able to know when that process has concluded by revisiting the

At this point, the manuscript should be searchable within the main website.

### Indexing MEI and activating OMR search

To add OMR search functionality to a manuscript, a set of MEI 5 files for the manuscript needs to be added to the [production MEI files repository](https://github.com/DDMAL/production_mei_files). Add these files in a folder named with the Cantus Database source ID for the manuscript. The mei files must be named by the following convention: *_[folio_number].mei. Once these are committed to the main branch of the production MEI files repo, they can be pulled with the rest of the Cantus Ultimus code base (the production MEI files repository is a submodule of the CU repo).

In the running `app` container, run the `index_manuscript_mei` command with the first command line argument being the source ID of the manuscript. Additional command line options can be found in that command's help text. Once this command has completed, the manuscript MEI has been indexed in Solr.

Go to the Cantus Ultimus admin page and ensure that the "Neume Search" and "Pitch Search" plugins exist in the database. If they do not, simply create new plugins with those names. Then, find the manuscript whose MEI you are adding in the admin panel. On that manuscript's admin page, select either the "Neume Search" plugin (if the manuscript's neumes are unpitched) or both the "Neume Search" and "Pitch Search" plugin (if the manuscript's neumes are pitched). Save the manuscript form.

When you navigate to that manuscript's detail view, OMR search should be available in the search panel.


## Manuscript Inventory

| Name | Provenance | Siglum | Cantus DB Record | IIIF Manifest | Supported | Served on cantus.simssa.ca | Notes |
Expand Down
10 changes: 9 additions & 1 deletion app/public/cantusdata/admin/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ class ManuscriptAdmin(admin.ModelAdmin):
),
(
"Status",
{"fields": ["public", "chants_loaded", "is_mapped", "dbl_folio_img"]},
{
"fields": [
"public",
"chants_loaded",
"is_mapped",
"dbl_folio_img",
"plugins",
]
},
),
]
readonly_fields = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,23 @@ def test_get(self) -> None:
}
response_no_manuscript = self.client.get(url, params_no_manuscript)
self.assertEqual(response_no_manuscript.status_code, 400)
params_no_type: dict[str, str | int] = {"q": "u d u", "manuscript": 123723}
params_no_type: dict[str, str | int] = {
"q": "u d u",
"manuscript_id": 123723,
}
response_no_type = self.client.get(url, params_no_type)
self.assertEqual(response_no_type.status_code, 400)
params_no_q: dict[str, str | int] = {
"type": "contour",
"manuscript": 123723,
"manuscript_id": 123723,
}
response_no_q = self.client.get(url, params_no_q)
self.assertEqual(response_no_q.status_code, 400)
with self.subTest("Test response"):
params: dict[str, str | int] = {
"q": "u d u",
"type": "contour",
"manuscript": 123723,
"manuscript_id": 123723,
}
response = self.client.get(url, params)
self.assertEqual(response.status_code, 200)
Expand Down
8 changes: 5 additions & 3 deletions app/public/cantusdata/views/search_notation.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SolrQueryResultItem(TypedDict):
class NotationSearchResultItem(TypedDict):
boxes: list[dict[str, Union[int, str]]]
contour: list[str]
semitones: list[str]
semitones: list[int]
pnames: list[str]
neumes: NotRequired[list[str]]

Expand All @@ -53,7 +53,7 @@ class SearchNotationView(APIView):
def get(self, request: Request, *args: Any, **kwargs: Any) -> Response:
q = request.GET.get("q", None)
stype = request.GET.get("type", None)
manuscript_param = request.GET.get("manuscript", None)
manuscript_param = request.GET.get("manuscript_id", None)
rows_param = request.GET.get("rows", "100")
start_param = request.GET.get("start", "0")

Expand Down Expand Up @@ -134,7 +134,9 @@ def do_query(
result: NotationSearchResultItem = {
"boxes": boxes,
"contour": d["contour"].split("_"),
"semitones": d["semitone_intervals"].split("_"),
"semitones": [
int(st) for st in d["semitone_intervals"].split("_") if len(st) > 0
],
"pnames": d["pitch_names"].split("_"),
}
neume_names: Optional[str] = d.get("neume_names")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default Backbone.Collection.extend({
var manuscript = _.result(this.parameters, 'manuscript');

if (manuscript)
queryParams.manuscript = manuscript;
queryParams.manuscript_id = manuscript;

return GlobalVars.siteUrl + "notation-search/?" + Qs.stringify(queryParams);
},
Expand All @@ -48,6 +48,7 @@ export default Backbone.Collection.extend({
*/
parse: function (response)
{
this.numFound = response && response.numFound || 0;
return response && response.results || [];
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default Marionette.Object.extend({
fields: [
{
name: 'Neume',
type: 'neumes'
type: 'neume_names'
}
]
},
Expand All @@ -44,20 +44,21 @@ export default Marionette.Object.extend({
fields: [
{
name: 'Pitch',
type: 'pnames'
type: 'pitch_names'
},
{
name: 'Pitch (invariant)',
type: 'pnames-invariant'
type: 'pitch_names_invariant'
},
{
name: 'Contour',
type: 'contour'
},
{
name: 'Interval',
type: 'intervals'
}
// TODO: Implement interval search (see #875)
// {
// name: 'Interval',
// type: 'intervals'
// }
]
}
],
Expand All @@ -68,7 +69,7 @@ export default Marionette.Object.extend({

var manuscriptModel = options.manuscript;

this.manuscript = manuscriptModel.get('siglum_slug');
this.manuscript = manuscriptModel.get('id');
this.neumeExemplars = new Backbone.Collection(manuscriptModel.get('neume_exemplars'));

this.fields = [];
Expand Down Expand Up @@ -146,9 +147,12 @@ export default Marionette.Object.extend({

getSearchMetadata: function ()
{
var numFound = this.results.numFound || 0;
return {
fieldName: this.field.name,
query: this.query
query: this.query,
displayedQuery: this.query,
numFound: numFound
};
},

Expand Down Expand Up @@ -180,7 +184,7 @@ export default Marionette.Object.extend({
var contourChoices = new ContourChoiceView();
inputView.listenTo(contourChoices, 'use:contour', function(newQuery)
{
inputView.insertSearchString(newQuery, false);
inputView.insertSearchString(newQuery, true);
});
regions.searchHelper.show(contourChoices);
}
Expand Down
Loading