I dette forløb skal det handle om “sundhedswearables”. På 8 moduler (à 100 min.) skal der fremstilles en enhed, der kan hjælpe patienter med genoptræning efter et slagtilfælde, apopleksi, som er betegnelsen for en blødning eller blodprop i hjernen. Helt konkret skal der udvikles og programmeres et træningsprogram, som patienten kan bruge via et “smartur” – en såkaldt M5StickC, og hvor patienten i højere grad, end hvad tilfældet er i dag, kan forestå egen behandling hjemme – og følge udviklingen.
Med udgangspunkt i den iterative metode (introduceres lidt grundigere i 2. modul) udvikler eleverne således et produkt, som kan kobles til komplikationer forbundet med motoriske udfordringer som følge af en blodprop i hjernen. Eleverne vil få en forståelse af, hvordan deres teoretiske viden kan omsættes til virkelige løsninger for andre mennesker.
Skønt forløbet er tænkt afviklet i sin helhed – og med udgangspunkt i moduloversigten, så skal sidstnævnte endelig ikke tænkes så stram og rigid, at man ikke sagtens kunne udelade visse moduler. Alternativt kan man også nøjes med modulerne 1-7, og f.eks. lade disse indgå i et helt andet forløb med særligt fokus på IoT / embedded computing, dvs. undlade at bruge modul 8, som alene omhandler plot i webinterface (HTML og JavaScript) og et afsnit om arkitekturer.
Endelig er der lagt op til, at forløbet kan danne rammen om en projektrapport.
Didaktiske overvejelser
Der er tilstræbt at undgå for meget af en ”bottom-up” tilgang, særligt til tekstprogrammeringen, da dette – som det efterhånden er almindelig anerkendt – alt for ofte resulterer i for snævre faglige kompetencer og ikke mindst giver udfordringer med motivationen for de elever, der ikke nødvendigvis er voldsomt it-interesserede. I stedet er projektets delmål udformet ud fra en “worked examples“-tilgang.
Endelig er det håbet, at forløbet kan vække en interesse og begejstring ved at være så stærkt løsningsorienteret og ved at tage udgangspunkt i teknologier, f.eks. “smarte” armbåndsurer, som eleverne allerede har et vist kendskab til – alt imens der opdyrkes eller -øves computational thinking / datalogisk tænkning.
Faglige mål:
Forløbet kan bruges på såvel C som B-niveau, idet den enkelte lærer kan justere dybden af opgaveløsningens enkelte dele, og går umiddelbart på tværs af fagets 7 kernestofområder. Foruden programmering og interaktionsdesign dækkes således også:
- Konstruktion af it-system som løsning til en problemstilling, herunder at behandle problemer i samspil med andre fag, nærmere bestemt biologi, samt at demonstrere viden om fagets identitet og metode
- It-systemers og menneskelig aktivitets gensidige påvirkning
- Repræsentation og manipulation af data
- Innovation
Endelig skal det bemærkes, at flere af modulerne er forsynet med en “lærernote”, der skal tjene til at gøre det helt klart, hvad der er formålet i det pågældende modul – samt komme med forslag til forskellige måder at gribe eventuelle opgaver an på.
1. Modul
Slagtilfælde er en af de største årsager til langsigtede handicap på verdensplan. Hvert år er der omkring 42,4 millioner tilfælde af slagtilfælde, som resulterer i at 80% af de udsatte får permanente motoriske handicap. Således er slagtilfælde en førende årsag til handicap. Evnen til at leve uafhængigt efter slagtilfælde afhænger i høj grad af mindskelse af motorisk svækkelse og genvinding af motorisk funktion.
Genoptræning
Nøjagtig forudsigelse af motorisk svækkelse hjælper til planlægning af et genoptræningsforløb og understøtter en realistisk målsætning for patienter. Dette lægger en stor byrde på enkeltpersoner og samfundet. Rehabilitering efter slagtilfælde består oftest af et forløb, hvor man løbende vurderer og evaluerer patientens formåen. På den måde kan genoptræningsprogrammet løbende forbedres og tilpasses i forhold til den enkeltes patients fysiske kunnen.
For at genoptræningen skal lykkes kræves der en specialiseret uddannelse, hvilket ofte er begrænset af manglende ressourcer i sundhedssektoren. Ydermere ses det at patienterne der er blevet udskrevet fra et seks måneders genoptræningsforløb, at 65% af patienterne fortsat er ude af stand til at bruge de berørte muskelgrupper i hverdagens aktiviteter, hvilket viser et behov for yderligere behandling.
Wearable-teknologi har potentiale
Her ses “wearable-teknologi som brug af sensorer” at have et stort potentiale til objektivt at vurdere og overvåge patienter i og især uden for kliniske miljøer. Bærbare sensorer, kan således reducere evalueringstider og via objektive kvantificerede data om patienternes evner bruges som supplement i en helhedsvurdering. Dertil kommer eventuelle besparelser i sygehusvæsenet, og i 2015 kunne Goldman Sachs konkludere, at brugen af IoT, eller rettere IoMT (Internet of Medical Things), alene kunne spare USA 300 milliarder dollars i årlige hospitalsudgifter.
Disse wearable-teknologier gør det også muligt at indsamle data ubemærket, og på den måde gør det muligt at undersøge motoriske funktioner, mens patienterne udfører dagligdags aktiviteter. Desuden er der et stort potentiale i at bruge sensorerne til at træne patienterne i at udføre præcise og funktionelt muskelarbejde. Det kan ske via hurtig og direkte respons til en patients bevægemønster ud fra en programmering af bevægelsessensorer.
Materialer og litteratur:
- TED Talk: Gary Wolf om “The Quantified Self“
I det foregående er selve casen fremlagt: hvordan kan man ved hjælp af en sundheds-wearable hjælpe en bestemt patientgruppe, i dette tilfælde personer, der har haft en blodprop, med genoptræningen i eget hjem. Dette forløb bygger på en såkaldt M5StickC, der er en ESP32-baseret mikrocontroller med bl.a. indbygget WiFi, infrarød-sender, mikrofon, LED og en 6-akse bevægelsessensor. Derudover er den udstyret med 2 programmerbare knapper – og med god mulighed for udvidelser med øvrige sensorer, herunder en EMG-sensor, der måler den elektriske aktivitet i musklerne.
Enheden, dvs. uret, forbindes til en computer vha. et USB-kabel. Uret er udstyret med en USB-C port, så det kan muligvis blive nødvendigt med en omformer til USB-A. Softwaren, som vi blive brugt i dette forløb, er Mu-editor, og programmeringssproget er Python (MicroPython). Der er desuden udviklet en glimrende, dansksproget brugerguide til M5StickC, som kan findes på adressen: https://m5guide.readthedocs.io/da/latest/.
Forudsat at uret er sluttet til computeren og softwaren startet, så er du nu klar til at programmere. For at komme i gang, og sådan at alle er med, så kan du passende finde en makker, hvor I skiftes til at løse de enkelte opgaver nedenfor. Det er dels vigtigt for læringen, men ikke mindst for ejerskabsfølelsen, at alle får “fingrene” i materien. Uanset om I arbejder i grupper eller ej, så opfordres alle til selv at taste koden ind, frem for blot at copy/paste denne.
Så snart uret er forbundet til computeren, så vil Mu-editor gøre dig opmærksom på, at den har registreret det – som vist nedenfor:
Klik på knappen “REPL”. Dette åbner bl.a. en terminal nede i bunden af programmet, som du blot kan se bort fra for nu. I det store, hvide vindue kan du ganske enkelt begynde at indtaste kode, og du opfordres til simpelthen straks at prøve kræfter med opgaverne i det følgende. Når koden er skrevet ind, så trykker man “Run” – og man får resultatet med det samme:
Brug nu M5-guiden til at løse følgende opgaver:
Opgave 1: brug urets LCD-display
- få urets LED til at lyse – og blinke
- tegn to forskellige geometriske figurer
- skriv noget tekst på skærmen
Opgave 2: brug knapperne
- registrer tastetryk på henholdsvis A og B
- registrer antallet af tryk på én af knapperne
- få knap A til at tælle en variabel op – og få B til at tælle variablen ned
Opgave 3: brug højtaleren
- få uret til at bippe, hver gang du trykker på en knap
- få uret til at bippe i forskellige toner afhængig af knappen
- få uret til at bippe, fra du trykker på A – og til du trykker på B
Materialer og litteratur:
- Guide til M5Stick: https://m5guide.readthedocs.io/en/latest/index.html
- Mathiasen, Ken: Informatik C. Praxis, 2017, ss. 177-191
- Guide til “Pair-Programming“
- Introduktion til Python-programmering:
- Variable, udtryk og typer: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/1/1.pdf
- Forgreninger og løkker: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/1/2.pdf
- Tekststrenge: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/2/1.pdf
- Lister og dictionaries: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/2/2.pdf
- Funktioner og moduler: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/3/2.pdf
2. Modul
Dette modul forudsætter, at du nu har installeret Mu, fået en tilstrækkelig indføring i programmeringssproget Python samt endelig fuldført de indledende opgaver, som skulle få dig godt i gang med at bruge M5Stick’en. Udover hvad du har lært i 1. modul omkring programmeringsstrukturer mv., så vil dette modul hjælpe med at pege dig i retning af funktioner, som du skal implementere i 3. modul.
Find sammen med din makker – eller overvej e.v.t. at finde en anden for variationens skyld – og gå så ellers i gang med at arbejde med urets bevægelsessensor (IMU). Formålet er at se, hvordan man hensigtsmæssigt repræsenterer fysisk bevægelse – og handler på denne – i kode. Hertil kan 3D-modellen i Processing i næste menupunkt understøtte dit/jeres eksperimentelle arbejde. Softwaren kan hentes her, og man kan for at spare tid nøjes med at installere Processing på én computer. Der er i øvrigt god mening i, at I fordeler arbejdet mellem jer, sådan at én person har Mu åben – og en anden Processing.
3D-model af M5Stick
Start med at åbne et nyt vindue i Mu-editor, skriv følgende kode ind – og tryk “Run“:
from lib import imu
import time
import fusion
myIMU = imu.IMU()
filter = fusion.MahonyFilter()
while True:
filter.update(myIMU.acceleration, myIMU.gyro)
print(str(filter.roll)+','+str(filter.pitch))
time.sleep(0.02)
Ovenstående skriver kontinuerligt værdier i konsollen, som illustreret nedenfor:
Du er nu klar til at bruge urets output, og så snart Processing er installeret, så hentes 3D-modellen af uret her. Importér modellen, ret i serielporten – og tryk på “Play”-ikonet. Du vil nu kunne se urets orientering i rummet afspejlet direkte i vinduet.
Nedenunder selve uret vil man desuden kunne aflæse henholdvis roll og pitch – værdier, som du/I så skal forsøge at eksperimentere jer til tærskelværdier ud fra. Hvordan ser værdierne (intervallerne) f.eks. ud, fra man holder armen strakt ud, vinkelret på kroppen – og til man har armen løftet strakt, lige op i forlængelse af kroppen (strakt op i vejret)?
Jeres træningsprogram skal som bekendt bygge på, hvor meget – og hvor hurtigt – patienten faktisk er i stand til at bevæge de pågældende lemmer.
OBS: Som vist nedenfor, så er det nødvendigt at ændre porten til den rigtige for dit system. Hvis du f.eks. bruger Mac, så kan du gå op i Spotlight – søge på Terminal, og inde i det pågældende Terminal-vindue skriver du \(ls\) \(/dev/tty.usb*\) og trykker Enter.
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis, 2017, ss. 193-226
- https://informatik.systime.dk/?id=p939
I det foregående har I arbejdet med uret ud fra en 3D-model, hvilket gjorde jer i stand til rent grafisk at eksperimentere jer frem til nogle intervaller for visse bevægelser. Dette arbejde fortsættes i det følgende, hvor I direkte i koden skal arbejde med M5Stick’ens orientering i rummet pba. urets accelerometer og gyroskop. Urets bevægelsessensor, eller IMU (Inertial Measurement Unit), har 6 frihedsgrader, og betragtet under ét får man således mulighed for at måle:
- hvor hurtigt, man roterer (gyroskop)
- hvor hurtigt, man accelererer eller bremser (accelerometer)
- tyngdekraften fra jorden, og dermed hvilken retning, der er nedad (accelerometer)
Når man skal finde ud af, i hvilken retning uret peger, så skal accelerometer- og gyroskopværdierne omregnes til vinkler (ift. jordens overflade). Dette sker med hjælp fra én ud af adskillige mulige såkaldt sensor fusion-algoritmer. Det nødvendige Fusion-bibliotek kan eleverne hente her – og overføre til uret vha. af M5-guiden. Men inden I kommer så langt, så forsøg – nu med udgangspunkt i selve koden – at eksperimentere med accelerometret alene:
from lib import imu
import time
myIMU = imu.IMU()
while True:
time.sleep_ms(10)
print(myIMU.acceleration)
Læg uret helt fladt på bordet. I får i konsollen kontinuerligt printet tre værdier, (x, y, z) – hvad sker der umiddelbart, dvs. hvilke værdier ændrer sig, når I drejer uret om sin egen akse?
Prøv nu at tage uret på med M5-Knappen tættest på håndleddet, og ændr så programmets \(while\)-løkke til følgende:
while True:
ax, ay, az = myIMU.acceleration
print(ay)
Ovenstående skriver en del af outputtet fra accelerometret til en variabel, \(ay\), som I så “printer” til konsollen. Hvad sker der med værdien, når I henholdsvis løfter/sænker armen? Notér jer – ligesom i jeres arbejde med 3D-modellen – nogle passende intervaller, og overvej:
- … hvorvidt intervallet kan bruges til at evaluere en øvelses korrekte udførelse?
- … hvordan man i så fald skulle implementere dette? (Hint: betingelser/forgreninger)
Materialer og litteratur:
- https://m5guide.readthedocs.io/en/latest/accelerometer_gyro.html
- https://m5guide.readthedocs.io/en/latest/sensorfusion.html
- Variable, udtryk og typer: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/1/1.pdf
- Forgreninger og løkker: https://imada.sdu.dk/~sjlarsen/teaching/python/slides/1/2.pdf
I skal nu prøve at udbygge eksemplet fra det foregående.
1) Importér først yderligere to biblioteker (forudsætter at fusion.py ligger på uret):
import fusion
from m5stack import lcd
2) Tilføj dernæst følgende – ét eller andet sted før \(while\)-løkken:
filter = fusion.MahonyFilter()
count = 0
lcd.orient(lcd.LANDSCAPE)
lcd.clear()
I 1) importerer vi de biblioteker, der gør det muligt at bruge IMU’en mere detaljeret (kombinere accelerometer og gyroskop), ligesom vi får mulighed for at skrive til urets display. I 2) sætter vi to variabler, hhv. \(filter\) og \(count\), hvor førstnævnte kommer til at indeholde de aktuelle værdier fra kombinationen af accelerometer og gyroskop, og sidstnævnte variabel sættes til 0, men vil senere i løkken blive talt op med én. Endelig “nulstiller” vi urets display.
Vi har kun tilbage at udvide \(while\)-løkken en smule – dels med vores \(filter\)-variabel, dels med en forgrening/betingelse, som hele tiden tjekker for, hvorvidt variablen \(count\) er lig med 20. I fald den er, så nulstilles den – og gennemløbet starter forfra:
while True:
filter.update(myIMU.acceleration, myIMU.gyro)
if count == 20:
lcd.print(filter.pitch, 20, 10)
lcd.print(filter.roll, 20, 30)
count = 0
count += 1
Prøv nu i egne ord at gøre rede for, hvad der har ændret sig i outputtet? Hvordan er de data, I får, forskellige, fra øvelsen uden brug af fusion-filtret, dvs. med accelerometret alene – kunne man bruge dem direkte? Modificér og udvid ovenstående kode, så urets display f.eks. skifter farve, så snart man vender uret på hovedet.
Som koden er på nuværende tidspunkt, så får man blot outputtet printet direkte i konsollen – eller i urets display. Man kan i stedet gemme disse lokalt på uret – i eksemplet nedenfor under filnavnet “data.csv”. De kan så efterfølgende flyttes over på din egen computer til videre behandling.
from lib import imu
import time
import fusion
myIMU = imu.IMU()
filter = fusion.MahonyFilter()
f = open('data.csv', 'w')
data = ''
t = 0
for count in range(200):
filter.update(myIMU.acceleration, myIMU.gyro)
data += str(filter.roll)+',\n'
t +=20
print('('+str(filter.roll)+','+str(filter.pitch)+')')
time.sleep(0.02)
f.write(data)
f.close
Materialer og litteratur:
- https://m5guide.readthedocs.io/en/latest/accelerometer_gyro.html
- https://m5guide.readthedocs.io/en/latest/sensorfusion.html
Kravspecifikation – og brugsmønstre (“use cases“)
Som oftest vil det være sådan, at man som udvikler mødes af en kunde, som måtte have en række krav til et endeligt it-produkt. Disse krav er i udgangspunktet løst formulerede tanker og forestillinger om given funktionalitet, og det er nu udviklerens opgave – i samråd med kunden – at give disse krav en så præcis og evaluerings- og testbar formulering som muligt.
Foruden en vis forståelse for selve det problem, der søges løst, hvad der også benævnes domænekendskab, så er det i selve analysefasen ligeledes afgørende at overveje de måder, hvorpå it-produktet forventes brugt, nemlig brugsmønstre.
Idet “produktet” i dette undervisningsforløb, nærmere bestemt uret, sætter nogle åbenlyse begrænsninger, så er det en rigtig god idé at skelne mellem, hvad man kunne kalde primære og sekundære funktioner. Der skal mao. prioriteres i, hvad der er allervigtigst, og hvad de hyppigst brugte funktioner måtte være. Til at afdække disse krav udarbejder man såkaldte “brugsmønstre”, hvilket kunne formuleres i retning af: “patienten tager uret på og tænder det. Så vælger han/hun første menupunkt ved at klikke på knap A, hvorefter kalibreringsfasen begynder. Når denne er slut, så instrueres patienten via uret til at løfte f.eks. armen. Uret bipper 3 gange, når øvelsen er overstået – og patienten tages tilbage til hovedmenuen.“
Find som gruppe sammen med én anden gruppe, idet I skal:
- Overveje og nedskrive 3-4 forskellige brugsmønstre (“use cases”)
- Vurdere ud fra ovenstående, hvilke der er mest relevante
- Ændre i a) i lyset af punkt b)
- Udveksle deres brugsmønstre med nabogruppen
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis, 2017, ss. 165-68 & 204f
- https://informatik.systime.dk/?id=p1046
- Caspersen, M. E. og Palle Nowack: It-fagets metoder
3. Modul
Blodprop i hjernen
Når en person rammes af en blodprop i hjernen og mere specifikt i hjernens motoriske cortex, kan det medføre lammelser af bestemte muskler. Da nervebanerne fra cortex krydser over modsatte side i bunden af hjernen, vil en skade i venstre side af cortex give lammelser i højre sides muskler.
Ud over skader i motorcortex forårsaget blodpropper har det også vist sig at skader i områder, som ligger på ydersiden af thalamus, de såkaldte basalganglier, kan give problemer i motorisk indlæring.
Særligt bevægelser som vi er afhængige af sker automatisk, er i dette tilfælde et problem. Det er f.eks. basalganglierne, som gør at vi kan cykle og samtidig huske på at se dig for i trafikken.
Ud over blodpropper i basalganglierne kan samme symptomer ses ved f.eks. Parkinsons sygdom. Her ses de første symptomer ved, at patienten kan have problemer med at udføre daglige rutiner, der involverer motorik. Det kan være rutiner som at tage tøjet af og på, knappe skjorten og binde snørebånd, som pludselig bliver en udfordring, og går langsomt.
Lillehjernen
Ud over motorcortex og basalganglierne har lillehjernen også en stor betydning for bevægelsen og især inden for fintuning og koordinering af bevægelsen. Lillehjernen står for at modtage og koordinere nervesignaler fra både cortex, muskler, sener og led. På den måde kan lillehjernen sammenholde de planlagte bevægelser med de faktiske udførte bevægelser. Heri sker der koordinering og feedback til det motoriske område i cortex, som justerer bevægelsen alt efter feedback fra lillehjernen.
Skader på lillehjernen medfører således bevægelser, som er fragmenterede og rykvise, modsat den normale velkoordinerede bevægelse.
Ved genoptræning efter blodpropper i områder som involverer basalganglierne og/eller lillehjernen vil genoptræningsprogrammet kunne tage udgangspunkt i træning af fine bevægelser med fokus på at øge bevægelsernes hastighed.
Genoptræning
Genoptræning efter blodpropper kan i høj grad tage udgangspunkt i allerede indlærte bevægelser, som er blevet lagret i hjernen. Genoptræning kan heri gå ud på at finde nye veje til at genopdage/genfinde det tidligere indlærte. Dette kan ske ved at nye områder i hjernen overtager funktioner fra tabte og ødelagte områder i hjernen. Med fokus på at indlære en specifik færdighed, er det af stor betydning at have hjernens adaptation for øje.
Ved adaptation sker der en tilpasning af det allerede lærte til nye situationer, og de neurale ændringer sker som beskrevet primært i lillehjernen.
Genoptræningsprogram
I opbygning af et genoptræningsprogram skelnes typisk mellem tre overlappende stadier:
Forståelses: Er det stadie i indlæringen af en motorisk færdighed, hvor man arbejder med at forstå de enkelte dele af bevægelsen.
Den associative face: Er det stadie i indlæringen af en motorisk færdighed, hvor teknikken kun kan udføres, når man er meget bevidst og fokuseret, og hvor der er stor variation i hvor godt det lykkedes fra gang til gang.
Den automatiske fase: Er slutstadiet i indlæringen, hvor teknikken udføres med stor præcision hver gang, og uden at man behøver at koncentrere sig om det.
For at opnå den optimale motorisk læring er har præcis og hurtig feedback en stor betydning for succes. Man kan således arbejde med at indarbejde positiv feedback i form af belønning på baggrund af en bestemt succesfuld bevægelse.
Dette medfører en øget sandsynlighed for, at handlingen gentages. Belønningen skal være simpel og letforståelig. Det kan f.eks. være simple signaler i form af lysglimt eller lyde, hvilket skal sikre et let forståeligt og hurtigt feedback.
Når du efterhånden har sporet dig ind på nogle tærskeværdier for én eller flere af patientens fysioterapeutiske øvelser, og med viden fra foregående afsnit om vanskelighederne forbundet med motorisk indlæring og behovet for at træne finmotorikken og hastigheden i udførelsen af selv helt basale, fysiske opgaver, så er det tid til at omsætte disse til noget kode, som ikke bare registrerer bevægelserne, men sætter jer i stand til at handle på bestemte værdier, eller intervaller, og give patienten passende feedback. Inden vi gør dette, så kræves imidlertid en kort introduktion til funktioner i Python.
I deres umiddelbare form afviger funktioner i programmering ikke meget fra funktioner, som de kendes fra matematikundervisningen. Hvis man tager \(f(x)=2x+3\) som eksempel, så vil funktionen have et navn, her \(f\), og den siges at “tage” en værdi \(x\), som den så behandler inde i forskriften \(2x+3\). Hvis vi således putter tallet 2 ind i funktionen, så der står altså \(f(2)\), og forskriften fra før bliver da til \(2*2+3\), dvs. variablen \(x\) får simpelthen værdien 2 inde i selve funktionsforskriften.
En funktion har altså et bestemt navn og tager én eller flere såkaldte argumenter (svarende til værdi fra før), sommetider også kaldt parametre, som den så behandler videre inde i selve funktionen. Du har i øvrigt allerede brugt flere funktioner, bl.a. \(lcd.print(…)\) og \(sleep(…)\). En funktion kan således opfattes som en blok kode, der kun eksekveres, når man “kalder”, dvs. bruger, funktionen. De erklæres i Python ved brug af \(def\):
def vis_navn(fornavn):
print(fornavn + " Turing")
vis_navn("Alan")
Overvej nu, hvad ovenstående funktion gør, og prøv dernæst funktionen med noget andet end “Alan” – hvad sker der? Hvordan kunne man i øvrigt udbygge funktionen, sådan at den kommer med en fejlmeddelelse, hvis ikke argumentet fornavn er lig med “Alan”?
Hvis I nu vender jer mod jeres egne eksperimenter med intervaller for grænseværdier, og lad os sige, at I har fundet følgende for armløft, hhv. pitch = [30, -70] og roll = [-60, -80]. Disse kan vi nu omsætte, eller måske rettere oversætte, i overensstemmelse med det, vi lærte om i 1. modul, nemlig nogle variabler og en forgrening. Med udgangspunkt i eksemplet fra forrige modul (“Bevægelse i kode: del II“), så kunne en funktion se ud som følger:
def armloeft():
pitch_min = 30
pitch_max = -70
if (filter.pitch > pitch_max) and (filter.pitch < pitch.min):
print("Inden for tærskelværdierne.")
else:
print("Uden for tærskelværdierne.")
Og funktionen kan vi nu tage i brug ved at “kalde” den – f.eks. i en løkke som nedenfor. Husk at importere relevante biblioteker samt instantiere IMU’en (se “Bevægelse i kode: del II“). Prøv jeres kode af, og se, hvor følsom den er, og om der skal justeres på noget (outputtet skrives i konsollen i Mu-editor):
while True:
armloeft()
4. Modul
Det er nu tid til at kigge på de standardiserede genoptræningsøvelser, som fysioterapeuten forestår sammen med patienten. Nedenfor er et lille, repræsentativt udpluk, og det forventes ikke nødvendigvis, at man når igennem dem alle. Til gengæld skulle de gerne så småt bevidstgøre om, hvordan der dybest set er tale om samme kodemæssige grundstruktur for mange af øvelserne i genoptræningen (mere herom ifm. “Modellering” i næste modul).
Som det fremgår af det biologifaglige vedrørende blodproppernes påvirkning af hjernen, så resulterer skaderne typisk i fragmenterede, rykvise bevægelser, og det er således øvelsernes formål at genoptræne til mere flydende, hurtigere bevægelser.
Som figurerne ovenfor viser, så vil øvelserne typisk involverer træning i løft af armene: her først i en stilling, hvor man sidder ned og har albuerne helt tæt, parallelt til kroppen, og man løfter så sine underarme, så langt man nu kan. I den anden øvelse står man oprejst og foretager så en slags “fingergang” op ad væggen, nogenlunde fra samme højde som hoften – og så ellers så højt, som det er muligt.
Ovenstående 4 træningsøvelser bruges til at opøve og genvinde tabt styrke eller behændighed/fingerfærdighed i fingre og hænder. Prøv at udføre ovenstående, idet du – eller din makker – har EMG-sensoren på. Hvilke værdier kan i læse, dvs. hvor følsom er sensoren? Kan man skelne øvelserne fra hinanden ud fra sensoraflæsning alene?
Og endelig:
I øvelserne ovenfor trænes, hvad man kalder “indadrotation” samt “abduktion” og “adduktion” i skulderled, og som bidrager til skuldrenes styrke og stabilitet. Som ved de øvrige øvelser, så skal I gå eksperimentelt til værks – og brug så funktionen \(armloeft(…)\) i det foregående (“Implementering: funktioner“) som skabelon for en specifik træningsøvelse.
Nedenstående er en lidt mere avanceret funktion (bruger dog kun accelerometret), som kan tjene til at inspirere ift. brugerfeedback: foruden at display’et lyser grønt, så der bippes der også en enkelt gang, når man løfter eller sænker armen for hurtigt:
from m5stack import lcd
from flowlib import hat
from lib import imu
import time
myIMU = imu.IMU()
hat_spk0 = hat.get(hat.SPEAKER)
def bipBevaeg(tid, delay, tone):
ay_prev = 0
t = 0
lcd.clear()
lcd.print('Klar til bip.', 20, 30)
while t < tid:
ax, ay, az = myIMU.acceleration
if ay > ay_prev:
hat_spk0.sing(tone, 0.3)
lcd.clear(0xFFAA00)
ay_prev = ay+delay
lcd.clear()
time.sleep(0.3)
t+=5
lcd.clear()
lcd.print('Faerdig.', 20, 30)
Husk at eksekvere funktionen, f.eks. inden i en løkke – og justér på funktionens parametre, \(tone\) og \(delay\). Prøv med \(bipBevaeg(200, 0.025, 1500)\). Hvordan ville man i øvrigt gøre, hvis nu tonen skulle stige afhængigt af, hvor hurtigt man løfter armen (frem for i intervaller à \(delay=0.025\))? Kunne det måske være en idé at have en tone, som angav den stigning i hastighed, man som patient skal forsøge at efterstræbe, i stedet for det enkelte (0.3) bip i den faste tone (\(tone=1500\)).
Materialer og litteratur:
- Region Midtjylland: Standardiseret fysioterapeutisk genoptræningsintervention
- https://informatik.systime.dk/index.php?id=1083
Indtil nu har fokus været på funktionaliteten i selve løsningen, dvs. at få omsat de konkrete, fysioterapeutiske øvelser til bidder af kode, som der kan handles på – hvad enten dette var at give patienten feedback eller gemme resultaterne på uret til videre behandling. I det følgende skal det handle om selve brugergrænsefladen (UI), altså selve bindeleddet mellem bruger og system, og hvordan man udvikler et ordentligt og hensigtsmæssigt interaktionsdesign (IxD) – særligt i betragtning af urets beskedne, fysiske dimensioner – og bare to knapper.
For at komme hurtigt i gang med at arbejde med et menusystem, så anbefales det at tage udgangspunkt i “M5StickMenu”-biblioteket, der er udviklet særligt til formålet. Følg linket, og klik dernæst på den grønne knap (“Code“) på websitet – og vælg “Download Zip“:
Filen menu.py overføres nu til uret (brug e.v.t. M5Guiden). Nedenfor ses et eksempel på, hvad der som minimum kræves for at komme i gang, hvor kommentarerne gerne skulle tydeliggøre de enkelte trin:
# Initialiser menuen
test_menu = M5StickMenu()
# Definer punkter
punkt1 = MenuElement("1. Haender", tryk, [1])
punkt2 = MenuElement("2. Ben", tryk, [2])
punkt3 = MenuElement("3. Fingre", tryk, [3])
# Føj punkterne til menuen
test_menu.add_element(punkt1)
test_menu.add_element(punkt2)
test_menu.add_element(punkt3)
test_menu.start()
Grafisk kan processen også illustreres som nedenfor:
Ovenstående kan passende placeres i \(main()\). Det er vigtigt at pointere, at \(MenuElement()\) i udgangspunktet tager tre parametre, nemlig 1) en titel, 2) en brugerdefineret funktion og 3) parametre til den brugerdefinerede funktion. I dette eksempel har vi funktionen \(tryk()\), som kunne se ud som nedenfor, hvor nummeret på det pågældende menupunkt blot skrives ud i MU-editors konsol:
# Brugerdefinerede funktioner
def tryk(nummer):
print('Du valgte ' + str(nummer))
Tilbage er at hægte menusystemet op på M5Stick’ens to fysiske knapper, hvilket man kan gøre med en løkke, hvor to forgreninger/betingelser “lytter” efter tryk:
while True:
if btnA.wasPressed():
test_menu = test_menu.down()
if btnB.wasPressed():
test_menu = test_menu.enter()
time.sleep(0.01)
Funktionen, som blev vist i det foregående afsnit (“Brugerfeedback og -grænseflade“) kunne i øvrigt implementeres med følgende:
punkt = MenuElement("1. Ben m. bip", bipBevaeg, [200, 0.025, 1500])
test_menu.add_element(punkt)
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis 2017, ss. 180-2.
- https://informatik.systime.dk/?id=p939
5. Modul
Når det kommer til at udvikle brugervenligt interface design, så ydes en række gode råd, principper og såkaldte heuristikker, der kan opfattes som efterprøvede tommelfingerregler. Hertil kommer, at der forskes meget i “Usability“, hvor man søger at etablere, hvad der undertiden kan opfattes som forholdsvis subjektivt, på et mere objektivt grundlag (f.eks. Arnold Lunds USE Questionnaire).
Foruden Jakob Nielsens 10 heuristikker (og for så vidt også hans 5 succeskriterier for Usability) finder man Ben Shneidermans (University of Maryland) 8 råd:
- Strive for consistency
- Cater to universal usability
- Offer informative feedback
- Design dialogs to yield closure
- Prevent errors
- Permit easy reversal of actions
- Support internal locus of control
- Reduce short term memory load
Selvom ikke samtlige af ovenstående nødvendigvis giver mening ift. M5Stick’en, så kan de imidlertid være med til at stimulere overvejelserne over, hvad der rent faktisk gør en brugergrænseflade “god”? Hvornår er grænsefladen f.eks. let anvendelig, og hvor meddelsom skal menuen være over for brugeren?
Endelig er det relevant med overvejelser af denne slags:
- Visibility of system status
- Match between system and the real world
- Consistency and mapping
- Good ergonomics and minimalist design
- Ease of input, screen readability and glancability
- Flexibility, efficiency of use and personalization
- Aesthetic, privacy and social conventions
- Realistic error management
- Losability/findability of the mobile device
Find sammen med en gruppe, du/I ikke har arbejdet med tidligere i forløbet, og diskutér, hvilke af ovenstående råd og anbefalinger, I finder relevante for netop jeres case, dvs. både for og imod. I kan passende skiftes til at fremhæve ét eller flere. Såfremt de giver anledning til andre hensyn, der ikke lige umiddelbart fremgår af ovenstående, så skriv dem endelig ned – de skal bruges i det følgende.
Materialer og litteratur:
- Bertini, Enrico (m.fl.): “Appropriating and Assessing Heuristics for Mobile Computing” in: AVI, 2006.
- Nielsen, Jakob: “10 Usability Heuristics for User Interface Design“. NN/g 2020
- Shneiderman, Ben: Designing the User Interface. Pearson, 2009.
- Interaction Design Foundation (IxDF): “Ease of Use“
- Interaction Design Foundation (IxDF): “Mobile User Experience (UX) Design“
- Word Wide Web Consortium (W3C): Web Content Accessibility Guidelines
- Brug “M5StickMenu” og få en fornemmelse af, hvordan det virker (støt dig gerne til eksemplerne)
- Overvej med din makker, hvordan det kunne forbedres? (pile, rammer e.lign. som angivelse af valg)
- Byg i skitseform videre på menusystemet med udgangspunkt i relevant teori/heuristik
F.eks.
Kunne man ikke også genoverveje menuens meget stramme, hierarkiske opbygning? Strukturdiagrammatisk ser den således ud på nuværende tidspunkt:
Materialer og litteratur:
- Mathiasen, Ken: Informatik. Forlaget Praxis, 2017
- https://informatik.systime.dk/?id=p1010
I det følgende gives en kortfattet og overskuelig introduktion til modellering. Øvelserne nedenfor skal tjene til at åbne op for diskussioner omkring, hvad det mere præcist er for et problem, man ønsker løst, hvordan man giver en konkret bid af virkeligheden en abstrakt form, samt hvordan man fremadrettet går hensigtsmæssigt til problemstillinger.
På figuren nedenfor ses et lille udpluk af strækøvelser. De er ikke fuldkommen ens, mao. fokuseres der umiddelbart på noget forskelligt, men alligevel finder man ved en nærmere betragtning et vist overlap – i hvert fald når de skal repræsenteres i kode, som det var tilfældet i modul 2-4.
Formålet med at forsøge at se bort fra uvæsentlige forskelle i ovenstående øvelser, f.eks. hvorvidt man strækker ud i højre side eller venstre side, er, at man i så fald ender ud med en mere generel eller abstrakt model for dét, der i grunden er samme øvelse. Dette gør det dels nemmere at forstå, hvad der er væsentligt ved den pågældende øvelse, dels bliver det nemmere at opbygge sit træningsprogram ved kun at ændre nogle enkelte parametre – i stedet for at skulle kode samtlige øvelser, som om de var vidt forskellige.
Gå sammen med din sidemakker, idet I overvejer:
- Hvilke strækøvelser i ovenstående er helt ens?
- Hvad gør dem ens – ud fra den viden, I fik i 3. modul?
- Ville man alligevel kunne samle de forskellige øvelser i én “klasse”?
Foruden at give os en langt bedre forståelse for de indgående øvelser, så betyder det også, at vi kan genanvende disse, ligesom vi har meget lettere ved at supplere med flere øvelser i fremtiden. Så frem for at skulle tage udgangspunkt i hver enkelt ny patient, så kan øvelserne altså bruges på tværs – som vist med illustrationen nedenfor:
Vælger man at gruppere fænomenerne som ovenfor, hvor alle patienter i hvert fald deler dét, at de er brugere af uret, som skal hjælpe dem med deres fysioterapeutiske genoptræning på egen hånd i hjemmet, og at der som regel vil være et vist overlap i de øvelser, de skal udføre, så kan man opfatte “Patient” som én klasse og “Øvelse” som en anden. Vi er således gået fra mange, umiddelbart forskelligartede fænomener, og så til blot 2 klasser, på baggrund af hvilke vi kan lave objekter – dvs. dén repræsentation, som de alle er givet i it-løsningen, altså helt konkret som kode på uret.
Endelig har det stor betydning for, hvor meget information – og hvor mange valg – man behøver at introducere sin bruger for (informationsarkitektur), hvilket er emnet for næste modul.
Ressourcer
Nowack_Modellering(pdf)
6. Modul
Godt interaktionsdesign: mønstre og idiomer
Meget forskning synes at understøtte forestillingen om visse mønstre i menneskelig adfærd og aktivitet, særligt når det kommer til at interagere med it-systemer. Vi møder mao. systemerne med visse forventninger og har efterhånden anlagt særlige vaner ud fra vores mangeårige, daglige omgang med dem. Man kan således med fordel udnytte denne indsigt i sit design af interaktionen og dermed understøtte brugerne i deres brug af de pågældende systemer – hvad der undertiden også kaldes brugercentrering.
Ligesom med sprog så har også design visse idiomer og en egen metaforik (Tidwell, 2011), og hvis vi bestemmer et idiom til at være “en gruppe ord, der tilsammen bærer en bestemt mening, men at denne mening ikke kan aflæses direkte i de enkelte, indgående ord“, så bliver idiomatik inden for (UI) design, at visse elementer, f.eks. dropdown-menuer, radio-buttons, tap-gestures o.lign. kommer til at stå for noget, uden at denne viden nødvendigvis var fuldstændig indlysende, første gang vi brugte dem – de har ikke en direkte parallel ude i den virkelige verden. Til gengæld er de væsentlig mere effektive til at kommunikere til brugeren, hvad man kan eller skal i den givne situation – forudsat, at man “taler samme sprog”.
Generelle overvejelser ved små displays:
Det er klart, at M5Stick’ens fysiske størrelse (eng. ”real-estate”) sætter nogle åbenlyse begrænsninger, og det er derfor helt essentielt at overveje nøje, hvordan information i så fald prioriteres – og præsenteres. Helt overordnet og grundlæggende bør man tænke på sit system ud fra dets underliggende data og de opgaver, der forventes løst med det:
- Hvad skal vises for brugeren?
- Hvordan skal elementerne arrangeres, f.eks. alfabetisk?
- Hvad forventes brugeren at stille op med elementerne – klikke, trykke?
Opgave: Find sammen med din sidemakker, og giv 3 bud på hvert af ovenstående punkter – skriv dem ned, da de skal bruges i det følgende.
Det er umiddelbart oplagt med én eller anden form for liste-visning, som det er tilfældet med M5StickMenu, om end dette ikke nødvendigvis er den eneste rigtige måde at gøre det på. Man taler undertiden også om selve informationsarkitekturen (eng. IA: ”Information Architecture is the art of organizing an information space”), hvor man er optaget af, hvordan information arrangeres og struktureres, og forudsat at man tager udgangspunkt i en liste, så kunne man stille spørgsmål som:
- Hvor lang er listen?
- Er der plads i displayet?
- Kunne listen være endeløs (eng. ”bottomless”)?
- Er der tale om en flad eller hierarkisk liste?
- Bør man overveje én eller anden form for gruppering?
- Er informationen i punkterne hetero- eller homogene?
.. og i forlængelse heraf:
- Hvilken type information er associeret med hvert enkelt punkt?
- Er det bare titler / overskrifter?
- Er det thumbnails af én eller anden slags?
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis 2017, ss. 180-2.
- https://informatik.systime.dk/?id=p939
- Tidwell, Jenifer: Designing Interfaces. O’Reilly, 2011
- UX Planet: Information Architecture. Basics for Designers
Der er nu igennem to sessions, henholdsvis Interaktionsdesign I og II, stiftet bekendtskab med principperne for godt interaktionsdesign, og arbejdsspørgsmålene i det foregående har forsøgt at lægge op til refleksion over samt diskussion omkring mulighederne med M5Stick’en i lyset af dens begrænsninger/ udfordringer – og ikke mindst de træningsprogrammer, som der efterhånden er blevet udviklet til den.
Revider dine/jeres skitser og prototyper fra sidste modul – hvad kunne man tage med fra de to afsnit om interaktionsdesign? Test 2-3 forskellige udkast af et menusystem på en anden gruppe.
Læreplanen for informatikfaget kræver som noget helt naturligt, at man afslutter hver enkelt undervisningsgang med at dokumentere (i en logbog) dagens arbejde: tekst, kode, screenshots e.lign. Dokumentation er aldeles vigtigt for ethvert it-projekt, det være sig dokumentation og eksemplificering af selve brugen af systemet, komponenterne mv., men også for de mere “uhåndgribelige” elementer, herunder brugergrænsefladen og interaktionsdesignet, eventuelle datamodeller og database-layout. Disse sidste dele benævnes undertiden abstrakt dokumentation og dækker over sådan noget som rutediagrammer (eng. “flow charts“), entitet/relationsdiagrammer (E/R), klassediagrammer, strukturdiagrammer som i foregående modul, o.lign.
Foruden ovenstående – og din kildekode, så indgår også dine skitser og (grafiske) prototyper i den foreløbige dokumentation. Den endelige dokumentation vil i øvrigt indeholde resultaterne af evalueringen/brugertests (mere herom i 8. modul).
F.eks. flowchart over enkel menu
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis 2017, ss. 180-2.
- http://htx-elev.ucholstebro.dk/wiki/index.php?title=Flowchart
- https://informatik.systime.dk/?id=1010
7. Modul
Eleverne er nu ved vejs ende i forløbet, og det er blevet tid til at besøge den iterative udviklingsmodel igen – særligt fasen “Test og evaluering“. Selvom der har været lagt op til, at eleverne løbende er vendt tilbage til deres oprindelige kravspecifikation og revideret denne i lyset af nye opdagelser i forbindelse med deres eksperimentelle arbejde eller udviklingen af urets brugergrænseflade, så giver det god mening at foretage en foreløbig, samlet evaluering. Vi er interessede i at afdække, hvorvidt:
- Interaktionsdesignet fungerer efter hensigten
- Hvordan brugeren rent faktisk “bruger” systemet
- Om funktionaliteten er i overensstemmelse med kravene
- Hvordan brugeren reagerer på eventuelle fejl
Denne del af processen involverer som regel den kunde, man har udarbejdet løsningen for, men endnu vigtigere de tiltænkte brugere af systemet. Hvis sidstnævnte udgør en større gruppe, så kan man i stedet tage udgangspunkt i et repræsentativt udsnit heraf. Når det kommer til selve testen, så er der en håndfuld måder, hvorpå denne kan gøres forholdsvis systematisk. Én teknik er “tænke højt”-testen, hvor testpersonen ganske enkelt “tænker højt”, idet vedkommende bliver bedt om at udføre en række klart formulerede opgaver – udarbejdet pba. af selve kravspecifikationen.
Det er imidlertid ikke helt ligegyldigt, hvordan testen konstrueres: en åben test, hvor testpersonen blot får lov til at prøve løsningen af helt frit giver måske nok indblik i, hvad vedkommende finder brugbart eller mindre brugbart, men det vil næppe gøre udviklerne klogere på, om funktionaliteten nu også er, som den skal være. Bed eleverne finde sammen i de grupper, de har arbejdet i hidtil, og få dem til at formulere nogle konkrete opgaver ud fra kravspecifikationen, f.eks.:
- Påbegynd dén øvelse, der træner armløft
- Se et overblik over gennemførte øvelser – samt datoer
- Slet en overstået øvelse
Da det måske ikke lige er muligt at finde én, der rent faktisk tilhører målgruppen, så må eleverne enten prøve det af på en lærer, eller på en anden fra klassen, som ikke umiddelbart har samme opgaver som ovenfor. Bed nu gruppen, der iagttager, overveje og tage stilling til, hvordan de vil registrere brugerens “tanker”: skal de optage lyden? Lyd og billede? Eller skal de skrive det ned. Endelig kan læreren samle op in plenum, og eleverne kan i lyset af deres evaluering komme med bud på, hvordan testen kunne udføres endnu mere hensigtsmæssigt – samt hvad der så er næste skridt i udviklingsprocessen?
I har nu udviklet en konkret løsning på et aldeles håndgribeligt problem vedrørende apopleksipatienters behov for et individualiseret genoptræningsforløb og at dette kan forestås i eget hjem – og ikke mindst deres muligheder for selv at følge egen udvikling og bedring.
Derudover har I udarbejdet en brugertest, der her i anden omgang har givet jer endnu mere indsigt i, hvorvidt I lever op til jeres oprindelige kravspecifikation. Som altid er tid en knap ressource, og der er nok nogle i blandt jer, der, nu hvor I gerne skulle have opøvet kompetencerne, sidder inde med idéer til, hvordan man kunne forbedre løsningen endnu mere. Opgaven bliver nu – i overensstemmelse med fagets læreplan – at vurdere graden af innovation. Der gives endnu ikke en fast, accepteret definition af innovation, men nedenstående er efterhånden forholdsvis udbredt og anerkendt:
En it-løsning er innovativ, hvis:
- Den er ny
- Den er en forbedring (af noget eksisterende)
- Den er værdiskabende
Vi kan imidlertid kvalificere graden af innovation noget nærmere, og hertil findes en håndfuld anvendelige modeller. Vi vil i det følgende anvende den såkaldte 4P-model. Som vist på figuren nedenfor opererer modellen med fire P’er: paradigme, produkt, position og proces. Hver enkelt af disse kan så bestemmes i et spektrum fra inkrementel, dvs. mindre, trinvise forbedringer, hvor man taler om “do better“, til radikal, altså gennemgribende og omfattende, innovation, som handler om at “do differently“.
Undertiden vil man have en it-løsning, som synes at kunne placeres på flere eller endda alle fire, og i visse fagbøger tager man simpelthen det samlede areal, udspændt af punkterne, som graden af innovation — hvilket ikke nødvendigvis er tanken her. De fire P’er dækker over:
- Paradigme: en ændring i den “mentale model”, inden for hvilken virksomheden eksisterer
- Energiselskaber, der omlægger deres forretning ved at udnytte eksisterende infrastruktur ..
- En virksomhed, der går fra selveje til franchise ..
- Mikrofinansiering, hvor kredit og begrebet “fattig” gentænkes ..
- Produkt: et nyt produkt eller en grundlæggende ændring af et produkt
- Visse håndholdte enheder som smartphones ..
- Elbiler som en videreudvikling af den traditionelle bil ..
- Position: en ændring i selve den kontekst, hvori løsningen anvendes (også målgruppen)
- Cowboybukser, der før var forbeholdt nogle få, bliver pludselig mode ..
- Pulsmåleren, der er gået hen og blevet allemandseje i ure mv. ..
- Proces: den måde, hvorpå en løsning eller service stilles til rådighed
- E-banking som en videreudvikling af almindelig bankforretning ..
- Kronisk syge kan være til undervisning virtuelt via en robot ..
Bed arbejdsgrupperne foretage en innovationsanalyse ud fra ovenstående af deres egen løsning, og bed dem sammenholde med, hvad man gør på nuværende tidspunkt i sundhedsvæsenet? Følg op herpå ved at udvælge 1-2 grupper, der fremlægger deres overvejelser. I samme forbindelse kunne det være interessant at ægge dem til en diskussion over, hvornår IoT/teknologi i sundhedsvæsenet giver mening, og hvor det giver knapt så meget mening?
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis, 2017, ss. 137-49.
- https://informatik.systime.dk/?id=p1020
- https://informatik.systime.dk/?id=p1049
8. Modul
Datastruktur og repræsentation
Data i sig selv, hvad enten det er kostregistreringer, sportsresultater eller løbende logning af en given patients behandlingsforløb, er ikke meget bevendte, medmindre de gives en struktur, som gør det nemt og effektivt at arbejde med dem. Dertil kommer den måde, hvorpå selve strukturen repræsenteres. Bl.a. JSON (JavaScript Object Notation) er en måde at repræsentere struktureret data på og er utrolig udbredt i webapplikationer og IoT-enheder. En anden udbredt struktur er CSV (eng. “Comma-separated values“), som der er blevet brugt i modul 2, hvor værdier adskilles af f.eks. komma – og hvor én linje f.eks. repræsenterer ét koordinatsæt.
Man har indtil flere muligheder for at få visualiseret sine data, når man eksporterer disse i CSV-format. Udover ganske enkelt at importere dem i Excel, så kunne man også lave et simpelt webinterface, der gør det endnu nemmere for brugeren. Tag udgangspunkt i skabelonen nederst på siden under “Resources“. Denne kunne nu udbygges med muligheden for at uploade *.csv-filer – illustreret ovenfor.
Du får i din HTML som minimum brug for et \(file\)-element og en enkelt \(button\):
<input type="file">
<button id="minKnap">Visualisér data</button>
.. og så kan følgende JavaScript uden videre bruges:
document.getElementById("minKnap").addEventListener("click", function() {
var file = document.querySelector('input').files[0];
graphContents(file)
});
Ovenstående gør, at brugeren nu kan uploade sine data i CSV-format til webinterfacet, som så tegner grafen. Men hvad nu, hvis man i stedet ønsker at kunne overføre flere filer ad gangen (yderligere inspiration kan hentes her)? Og at de hver især endda genererer deres egen graf, så patienten bedre kan følge sin udvikling over tid? Det er opgaven nu, og vi er umiddelbart interesseret i følgende fra filen “graph.js”:
data: {
labels: [],
datasets: [{
label: '...',
fill: false,
backgroundColor: ...,
borderColor: ...,
data: [],
},
...
]
}
Hvert nyt dataset, forstået som hver ny “logning” eller *.csv-fil, skal ind i array’et \(datasets[…]\) – og i krøllede parenteser { … }. Dette kan man opnå programmatisk med følgende funktion. Kig den grundigt igennem med din sidemakker og prøv med egne ord at forklare, hvad der sker:
function graphContents(file) {
let reader = new FileReader()
reader.readAsText(file)
reader.onloadend = function() {
lastModified = new Date(file.lastModified);
var colorName = colorNames[num]
var newColor = window.chartColors[colorName];
var newDataset = {
label: 'Dataset',
backgroundColor: newColor,
borderColor: newColor,
data: [],
fill: false
}
data = this.result.split('\n');
newDataset.label = lastModified;
data.forEach((item, i) => {
item_splitted = item.split(',');
config.data.labels.push(item_splitted[0]);
newDataset.data.push(item_splitted[1]);
});
config.data.datasets.push(newDataset);
window.myLine.update();
num += 1
}
}
Som løsningen er skruet sammen på nuværende tidspunkt, så dannes y-aksen ud fra første “kolonne” af værdier i *.csv-filen – og x-aksen dannes ud fra anden kolonne. I det pågældende program på M5Stick’en forudsættes det således, at f.eks. pitch-værdien logges for hvert sekund (i ét eller andet antal sekunder). Sæt dig sammen med din makker og overvej, hvorvidt dette er hensigtsmæssigt? Ændr så i koden i overenstemmelse med jeres egen idé.
En anden problematik er endelig, at koden på nuværende tidspunkt kun kan håndtere 4 tekstfiler ad gangen – hvad sker der, hvis man tilføjer flere? Overvej med din sidemakker, hvordan man hensigtsmæssigt kunne kommunikere dette til brugeren. HINT: brug JavaScripts \(len\) til at tjekke antallet af elementer i array’et \(files\) (se funktionen \(handleFiles(files)\) i filen “drop.js” – og brug så \(alert()\) til at meddele brugeren noget meningsfuldt.
Materialer og litteratur:
- https://www.chartjs.org/
- https://informatik.systime.dk/?id=950
Ressourcer
drop(html)
Hidtil er data blevet logget til urets (begrænsede) hukommelse, og disse data har man så skullet hente ud af uret i CSV-format til videre behandling i fx Excel. I det følgende skal det handle om at overveje alternativer i lyset af, hvordan man forestiller sig, dataene skal tilgås: skal fysioterapeuten have uret, og så hente dem ud, eller skal dataene måske snarere sendes digitalt? Der skal nu opsættes en database, og der skal i denne forbindelse overvejes, hvordan dataene gives en hensigtsmæssig struktur, så de nemt og effektivt kan visualiseres og integreres i andre platforme.
I udgangspunktet skal dataene som sagt hentes ud manuelt ved at forbinde uret til computeren. Idet der tages udgangspunkt i apps, vi alle efterhånden er vant til at bruge på vores smartphone: fotos-App, spil, e-banking eller adgang til skolens intranet/Lectio, overvej da følgende spørgsmål med din sidemakker:
- Hvor er kontakter (tlf.nr. mv.) lagret henne?
- Hvor er billeder og videoer lagret henne?
- Og hvad med highscoren i ét af dine favoritspil?
Der er givetvis mange, der har deres fotos og videoer lagret “i skyen” (iCloud e.lign.) – hvad er fordelene og ulemperne ved dette? Hvordan tilgår man disse data, og hvordan præsenteres de? Overvej nu, hvordan dataene fra urene kunne gemmes og opbevares – og ikke mindst tilgås. Det kunne fx være nærliggende at indtænke dem i en 2-lagsarkitektur, hvor de enkelte ure, som illustreret på figuren (kan gives en mere formel form, UML, se under Materialer og litteratur) nedenfor, blot forbindes til en database, og hvor der så kan deponeres al den data, brugeren/patienten har logget:Det har først og fremmest den fordel, at fysioterapeuten – og patienten selv – nu ikke længere er afhængig af uret, dvs. dens begrænsede mængde hukommelse og det faktum, at man skal være i fysisk besiddelse af det. Tværtimod kan man tilgå dataene fra en ekstern server, som altid er tilgængelig. Hvis man ser på rollerne, så står klienten for:
- præsentationen over for brugeren: al grafik og information
- interaktionen: klikkene på A- og B-knapperne
- kommunikation med serveren
Og serveren står for:
- at modtage data fra klienten
- at behandle dataene – og opbevare disse
Spørgsmålet bliver nu, hvordan man kunne gøre patientens data tilgængelige for denne selv samt vedkommendes behandlere? Hvis man tager udgangspunkt i det simple website fra tidligere i modulet, og hvis man forudsatte, at dette ligeledes blev placeret (“hostet“) på en ekstern server, så kunne man pludselig udnytte en arkitektur som den nedenfor:Udover at udnytte de fordele, som tolagsarkitekturen, også kendt som klient-server-arkitekturen, gav os, så er der sket en yderligere spaltning af server-laget, sådan at vi ender ud med et såkaldt applikationslag og et databaselag. Websitet fra tidligere ville nu tilhøre applikationslaget, og man kunne forestille sig en udvidelse, der medførte, at sitet fremadrettet kunne håndtere alle de patienter, der var blevet udstyret med en M5Stick, og så selv koordinere med databaseslaget, hvilke data, der skal hentes – og hvornår. Nu har man, hvad der også benævnes trelagsarkitekturen.
Man kan afslutningsvis overveje, hvilke perspektiver der kunne være i, at urene nu som klienter kommunikerer med en server, fx at nye rehabiliteringsøvelser automatisk kunne “pushes” til, dvs. gøres tilgængelige for klienten, uden at man skulle have uret indleveret – og programmere direkte på det?
Materialer og litteratur:
- Mathiasen, Ken: Informatik C. Praxis, 2017, ss. 127-133.
- https://informatik.systime.dk/?id=p1099
- https://informatik.systime.dk/?id=p1124
- https://informatik.systime.dk/?id=p1134
- Fowler, M: UML Distilled – A Brief Guide to the Standard Object Modelling Language. Addison-Wesley, 2004