diff cpack/dml/lib/humdrum_p2r.pl @ 0:718306e29690 tip

commiting public release
author Daniel Wolff
date Tue, 09 Feb 2016 21:05:06 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cpack/dml/lib/humdrum_p2r.pl	Tue Feb 09 21:05:06 2016 +0100
@@ -0,0 +1,286 @@
+/* Part of DML (Digital Music Laboratory)
+	Copyright 2014-2015 Samer Abdallah, University of London
+	 
+	This program is free software; you can redistribute it and/or
+	modify it under the terms of the GNU General Public License
+	as published by the Free Software Foundation; either version 2
+	of the License, or (at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public
+	License along with this library; if not, write to the Free Software
+	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+:- module(humdrum_p2r, [ humdrum_import/1, hum_uri_path/2 ]).
+
+/** <module> Manages a database of Humdrum files and mappings to RDF.
+ */
+
+:- use_module(library(memo)).
+:- use_module(library(humdrum)).
+:- use_module(library(humdrum/humdrum_world), [with_kern_module/4]).
+:- use_module(library(fileutils)).
+:- use_module(library(termutils)).
+:- use_module(library(typedef)).
+:- use_module(library(dcg_core)).
+:- use_module(library(musiclab)).
+:- use_module(library(settings)).
+:- use_module(entailment(p2r)).
+
+:- set_prolog_flag(double_quotes,string).
+
+:- rdf_register_prefix(humdb,'http://dml.org/humdrum/data/').
+:- rdf_register_prefix(hum,'http://dml.org/humdrum/schema/').
+:- rdf_register_prefix(kern,'kern:').
+
+:- setting(kern_root,string,"~/lib/kern","Root of kern lib tree").
+:- setting(kern_subdirs,list(atom),[classical,lorraine,jrp,ragtime,ireland,pentatonic,idyom],"Kern library directories to import").
+
+uripattern:def( work(Opus), humdb:work/enc(Opus)).
+uripattern:def( trefcode(C), hum:refcode/trans/enc(C)).
+uripattern:def( refcode(C), hum:refcode/enc(C)).
+uripattern:def( kernfile(F), kern:tail(F)).
+
+% Humdrum schema
+rdf(hum:refcode('OTL'), rdfs:subPropertyOf, dc:title),
+rdf(hum:composer, rdfs:subPropertyOf, foaf:maker),
+rdf(hum:opus, rdfs:subPropertyOf, mo:opus),
+rdf(hum:'Work', rdfs:subClassOf, mo:'MusicalWork'),
+rdf(hum:'File', rdfs:subClassOf, mo:'Score'),
+rdf(hum:encodedBy, rdfs:type, rdf:'ObjectProperty'),
+% rdf(hum:encodedBy, owl:inverseOf, hum:encodes) <== true.
+
+rdf(\refcode(C), rdfs:subPropertyOf, \trefcode(C)) <==
+   setof(C, translated_refcode(C), Codes),
+   member(C, Codes).
+
+rdf(\trefcode(C), rdf:comment, Desc1) <==
+   setof(C, translated_refcode(C), Codes),
+   member(C, Codes),
+   hum_prop_desc(C,Desc),
+   atom_concat(Desc,' (translated)',Desc1).
+
+translated_refcode(Code) :-
+   browse(file_props(_,Props)), 
+   member(Code-((sec-_)-_),Props).
+   
+hum_prop_desc(C,_) ==>
+   rdf(\refcode(C), rdf:type, rdf:'ObjectProperty'),
+   rdf(\refcode(C), rdf:domain, hum:'File').
+
+hum_prop_desc(C,Desc) ==>
+   rdf(\refcode(C), rdf:comment, literal(Desc)).
+
+% -- mappings that use file_opus/2 ---------------
+
+%% file(-File) is nondet.
+%  True when File is a Humdrum file that has been imported into
+%  the current database.
+:- dynamic file/1.
+
+%% file_opus(-File,-Opus) is nondet.
+%  True when Humdrum file File contains an SCT refcode
+%  (scholarly catalog number) Opus.
+file_opus(F,O) :- file(F), file_prop(F,'SCT',_,O).
+
+rdf(\kernfile(F), \trefcode(C), literal(Value)) <==
+   call_with_mode(browse,file_prop(F,C,sec,Value)).
+
+rdf(\kernfile(F), \refcode(C), literal(Value)) <==
+   call_with_mode(browse,file_prop(F,C,pri,Value)).
+
+rdf(\kernfile(F), hum:directory, literal(Dir1)) <==
+   file(F),
+   file_directory_name(F,Dir),
+   atom_concat('/',Dir1,Dir).
+
+file(F) ==> 
+   % rdf(\kernfile(F), hum:language, hum:language/humdrum),
+   rdf(\kernfile(F), rdf:type, hum:'File'). 
+
+file_opus(_,O) ==>
+   rdf(\work(O), rdf:type, hum:'Work'), 
+   rdf(\work(O), hum:opus, literal(O)). 
+
+% file_opus(F,O) ==>
+%    rdf(\kernfile(F), hum:encodes, \work(O)).
+
+
+% rdf(\work(O), dc:title, literal(Title)) <== 
+%    file_opus(F,O), 
+%    (file_has(F,'OTL',Title); file_has(F,'OTP',Title)).
+
+% rdf(\work(O), dc:title, literal(lang(Lang,Title))) <== 
+%    file_opus(F,O), 
+%    file_has(F,'OTL',Title), 
+%    file_has(F,'TXO',Lang).
+
+% rdf(\work(O), hum:partOf, humdb:parent_work/enc(P)) <==
+%    file_opus(F,O),
+%    (file_has(F,'OPT',P); file_has(F,'OPR',P)).
+
+% rdf(\work(O), hum:composer, humdb:agent/enc(C)) <==
+%    file_opus(F,O), file_has(F,'COM',C).
+
+% rdf(\work(O), hum:number, literal(Num)) <== 
+%    file_opus(F,O), file_has(F,'ONM',Num).
+
+% ----- mappings using composers/1 --------
+
+% rdf(humdb:agent/enc(C), foaf:name, literal(C)),
+% rdf(humdb:agent/enc(C), rdf:type, mo:'MusicArtist') <== 
+%    composers(Composers),
+%    member(C,Composers).
+
+% ----- mappings using parent_works/1 --------
+
+% rdf(humdb:parent_work/enc(P), rdf:type, hum:'Work'),
+% rdf(humdb:parent_work/enc(P), dc:title, literal(P)) <==
+%    parent_works(Works),
+%    member(P,Works).
+
+
+has_stripped(Recs,Prop,Status,Literal) :-
+   member(ref(Prop,Lang,RawValue),Recs),
+   split_string(RawValue,""," ",[String]),
+   String\="", atom_string(Value,String),
+   refcode_literal(Lang,Value,Status,Literal).
+
+refcode_literal(def,    Val, pri, Val).
+refcode_literal(P-Lang, Val, P,  lang(L,Val)) :- lang(Lang,L).
+
+:- type prop ---> prop(atom,atom,ground).
+:- volatile_memo file_props(+file:atomic,-props:list(prop)).
+
+file_props(File,Props) :-
+   setting(kern_root,Root0),
+   expand_file_name(Root0,[Root]),
+   string_concat(Root,File,Abs),
+   % !!! FIXME: will barf if Root contains funny characters
+   format(string(Cmd),"grep '^!!!' \"~w\"",[Abs]),
+   hum_read(pipe(Cmd),utf8,Recs),
+   setof(prop(Prop,Status,Lit),has_stripped(Recs,Prop,Status,Lit),Props).
+
+
+:- volatile_memo parent_works(-works:list(ground)).
+parent_works(Works) :-
+   writeln('% Compiling list of parent works...'),
+   setof(P, F^O^(file_opus(F,O),file_prop(F,'OPR',_,P)), Works).
+
+:- volatile_memo composers(-composers:list(atom)).
+
+%% composers(-Composers:list(atom)) is det.
+%  Compiles a list of composer names referenced in the current
+%  Humdrum file property database file_props/2.
+composers(Composers) :-
+   writeln('% Compiling list of composers...'),
+   findall(C, call_with_mode(browse,file_prop(_,'COM',_,C)), CList),
+   sort(CList,Composers).
+
+% rdf(URI,rdf:type,mo:'MusicArtist') <==
+%    composers(Comps),
+%    member(C,Comps),
+%    agent_uri(composer,C,URI).
+
+% rdf(URI,hum:name,literal(Name)) <==
+%    agent_uri(composer,Name,URI).
+
+% rdf(\kernfile(F), hum:composer, literal(Name)) <==
+%    call_with_mode(browse,file_prop(F,'COM',pri,Name)),
+   % agent_uri(composer,Name,URI).
+
+
+file_work_terms(File) -->
+   if(file_prop(File,'OTL',_,Title), [Title]),
+   if(file_prop(File,'OPR',_,Parent), [Parent]),
+   if(file_prop(File,'OPN',_,Opus), [Opus]),
+   if(file_prop(File,'SCT',_,Cat), [Cat]).
+
+
+file_prop(File,Prop,Status,Lit) :-
+   file_props(File,Props),
+   member(prop(Prop,Status,Lit),Props).
+
+
+hum_uri_path(URI,Path) :-
+   atom_concat('kern:',Rel,URI),
+   setting(kern_root,Root),
+   expand_file_name(Root,[Root1]),
+   string_concat(Root1,Rel,Path).
+
+
+%% humdrum_import(+Path:atom) is det.
+%
+%  Searches for files in the directory tree beneath
+%  =|<kern_root>/Path|=, where =|<kern_root"|= is the current
+%  value of the setting =|humdrum_p2r:kern_root|=. Path can
+%  be any relative path. Files are added to memoised property
+%  database predicate file_props/2.
+humdrum_import(Path) :-
+   setting(kern_root,Root0),
+   expand_file_name(Root0,[Root]),
+   with_status_line(
+      forall( (  kern_file(under(Root/Path),File), 
+                 atom_concat(Root,Rel,File),
+                 memo(file_props(Rel,_),_-ok)),
+              (  status(" Imported ~s",[Rel]), 
+                 id_assert(file(Rel))) )).
+
+:- volatile_memo scan_library_dir(+ground,-float).
+scan_library_dir(Dir,T):- humdrum_import(Dir), get_time(T).
+
+
+:- public import/0, import/1.
+import :- 
+   setting(kern_subdirs,Dirs), 
+   import(Dirs).
+import(Dirs) :- 
+   maplist(scan_library_dir,Dirs,_),
+   assert_all(humdrum_p2r).
+
+:- volatile_memo humfile_status(+string,-ground).
+humfile_status(Path,Status) :-
+   status(Path,[]),
+   catch( ( with_kern_module(Path,utf8,_,true) -> Status=ok
+          ; Status=fail),
+          Ex, Status=ex(Ex)).
+
+   
+humdrum_check :-
+    with_status_line( 
+      forall( (rdf_db:rdf(X,rdf:type,hum:'File'), hum_uri_path(X,Path)), 
+              (   humfile_status(Path,Status),
+                  (  Status=ok -> true
+                  ;  Status=fail -> format('\nFailed on: ~w\n',[Path])
+                  ;  Status=ex(Ex) -> format('\nException on: ~w\n',[Path]),
+                                      print_message(error,Ex)
+                  )
+               ))).
+
+kern_file(Findspec,File) :-
+   find_files(Findspec,File),
+   extension_in(File,[krn,kern,'KRN','KERN']).
+
+id_assert(Fact) :- call(Fact) -> true; assert(Fact).
+
+lang('ENG',en).
+lang('EN',en).
+lang('FRA',fr).
+lang('FRE',fr).
+lang('FR',fr).
+lang('DE',de).
+lang('DEU',de).
+lang('GER',de).
+lang('ITA',it).
+lang('IT',it).
+lang('NO',no).
+lang('NOR',no).
+lang('LAT',la).
+lang('LA',la).
+lang('RU',ru).
+lang('RUS',ru).