COVID-19 Dashboard Creation

I have been a fan of this forum and tinderbox for some time! My use of this has always been for my own personal projects an I have learned a great deal along the way from this forum. I have been struggling over the past few weeks and wanted to reach out and ask for some help. I am sorry for the long introduction, but I wanted to share this to bring context to the problem and to express my gratitude to the group. I am an anesthesiologist in the midst of the COVID-19 pandemic. I have taken on a great deal and am trying to learn as much as I can about something we knew very little about before December. Out of luck or some intervention, as I worked through learning about this disease I thought about using Tinderbox to collect my notes. When I opened the forum, and saw the header Mark posted, I was taken aback by this! It made me realize we are all in this together and I am so grateful for any and all help from this group. I wanted to say thank you for thinking of those in need around the world.

Now for my question and request for help - I have not done much with respect to export of documents so at some point I will come back to needing to export the document that is created to share with others in the hospital. But first, here are some thoughts I would like some feedback on as I approach building a dashboard to track the patients and resources in our hospital.

I have not done much with formatting notes into tables, I have seen some people format dashboards and could use some help and ideas on how to do this.

I am thinking of having the following prototypes:

Patient
Staff

Following Collections:

Emergency Department
MICU
SICU
CTICU
4S
5S

So the first question I have is how to create a resource/capacity table where I can count current census, ICU, Ventilator use and remaining?

Thoughts on how to best use this to track the patients - ultimately, it would be something I would need to export in a daily or 2-3 times daily document for staff to use so I would need some help on how to best start this so the export is meaningful.

Sort of looking for something like these images:

I was thinking of using a series of Adornments for the locations and setting actions that when a patient is dragged from one location to another, it would update their location. I am then thinking of using Agents to look for things such as Intubated (to keep a count of current ventilated patients), COVID test status, and other attributes that are important to track.

So in short, I am looking for any ideas and help on how to develop this document, which I think might become quite complex as I proceed. I think if I can get a handle on how to aggregate information into a table, I can start to work on laying this out.

I will ultimately need some help with exporting but I think it is too soon since I do not have a good idea of how to design the data. We can come back to this aspect later

Again I am thankful for any and all ideas on help on how to do something like this! Sorry for this being kind of nebulous right now, but I think this forum will have some ideas and insights that will be useful.

Thanks in advance.

Don

I don’t know if a table is what you’d like to see inside Tinderbox or rather upon export, but you could use the Container table display feature. This quickly tabulates the information in all your notes. Here is a quick easy example using a couple of system attributes:

All the best with your important work, and thank you.

I have looked at this feature, are you able to tabulate the sum of these features?? Such as count the number of notes that are intubated for example (if this is a boolean attribute)? Or is this feature something that runs on each note? It would be helpful to get a summary of patient statistics by locations (such as SICU). Thank you, I will work on using this to see if I can make this work for the project!

Appreciate the help
Don

[Ed. Summary tables don’t do tabulation: they’re quick and dirty overviews. Attribute Browser might help here; you could list Patients by Location, for example, and display Name and various patient characteristics in columns. – MB ]

I must admit I’ve not used this feature. But from the linked-to page, it appears you can use $TableHeading and $TableExpression to perhaps perform a sum of all the children notes, and this should then display in that map view.

Alternatively, you might explore using the Attribute Browser view. It can provide quick tabulations of total, mean, and more. It allows you to easily determine the scope of the browser’s ‘search’. You could set up a number of such Attribute Browsers in tabs, to always have different information at hand constantly updated.

I know that @mwra and @eastgate will step in and provide much better info and solutions than the rest of us can, but I suggest you get familiar with the Crosstab view, with CSV export, which is simpler than HTML, and the other quick export features. Also, if you could post a sample Tinderbox file with non-private or anonymized data for the forum readers to experiment with the kind of data you are working with, it might help the dialog.

Thank you for your service, @DMV

2 Likes

Thanks for the help!

Paul, Yes I think this is good. I am tied up at the moment but will share the start of my Tinderbox file so others can work with it and understand some of the attributes that would be useful. I hope to get back to this in a few hours. Thanks again!
Don

1 Like

Think first about what you need most, and what part of that is most urgent. A sample Tinderbox document will be a big help.

Ok here is what I have been able to hobble together. I have found the Staffing part has been working (I am using a collection to obtain the current active staff for a shift in the command center).

I am not sure if this is the right way to go about patients and locations. Right now I have created adornments for different COVID units. I am having some trouble changing attributes on children that are dragged onto each adornment (I would like to have the $UnitLocation changed to the name of the adornment ie SICU when they are moved from lets say 4 south to this unit).

I am also trying to determine how to best tally things such as negative pressure rooms remaining, number of intubated patients (and maybe other resources. Once I figure out the best way to track and count I can add any number of them as attributes).

I would like to create another table to display total counts for things such as number of patients with covid (ie by status), total number of ventilators in use and remaining (I would need to count the number in each ‘unit’ and then do the math. Not sure how to access these attributes from all of the various adornments (unless there is a better away to arrange these).

Here is a sample of what I have thus far. I will keep plugging away at this. Thanks in advance for any thoughts or directions to pursue.

COVID-19 Dashboard - Working File.tbx (155.5 KB)

Made some changes, I created Note collections for the locations instead of adornments (I thought adornments would behave like collections but they do not appear to do so). Please let me know if there is a use for adornments in this design. I am starting to get some of the aspects I was looking for. Here is an updated file

COVID-19 Dashboard - Working File.tbx (125.4 KB)

1 Like

Not sure this helps. With cross-tabs you can display generally display your notes in a 2D grid based on two attributes. With the addition of a well chosen display parameter in the controls above you can actually display one additional attribute. If for instance you would like to display your patient name, the status of their Covid-tests and whether they are located in SICU and MICU (or any other department) you can easily generate the following using the test file you provided:

Left you see the patient names, the columns represent their test status and I use the display to show the container for each note (MICU or SICU). The beauty of TinderBox is that you can display each note and click on it for additional information, editing or updating in the grid.

In a similar vein here an example now displaying the room number of the patient.

I sense that in addition to a better overview of your notes you would also like to address th Capacity and Occupancy Grid that you provided as illustration at the beginning of the post. If I’ve understood correctly the first column of your table is static e.g. the total capacity of critical care beds, ventilators etc… is a constraint that does not vary with time (unfortunately in many cases). The 2nd column however reflects the current number of patients and their medical equipment needs. Could you please confirm ?

Thank you Malcome (and Paul). I agree with both of you that I think the Cross-Tabs will be useful in this dashboard. I have to work more with this to understand. As I am working on this document, I am realizing there are more levels I should be thinking about. Let me see if I can outline these levels, and then also answer your question about current resources, patients and their needs.

As you see in the document (I am adding another update since I have begun to look at the idea from Tinderbox Way Summaries and Repeaters - still trying to figure out the correct rules to sum the children elements).

COVID-19 Dashboard - Working File.tbx (137.5 KB)

I am thinking about the following prototypes:

Patient

Room - with attributes - isNegativePressure, RoomNumber, Location (this would be SICU, MICU, 4S, etc). When A patient is assigned to a room, I would ‘drop’ a patent Note into the room (ie room would contain a patient).

Ward - Considering using an agent to ‘collect’ all Rooms that match Room.$Location with Ward.$Name. Then I could add additional attributes to calculate - Total number of rooms, Total occupied rooms would then be a sum of all children (rooms) that are occupied (ie have a child which is of type Patient).

Then would need a summary Agent (as I have now called Resources by Location) which would collect all the Wards and perform the calculations as I have them.

To answer your question - As we work through this Pandemic, the goal is to track our current capacity and that which remains. For example, by creating locations in the hospital (which I am calling Wards) and assigning the available rooms (these could be current physical rooms or other locations that have been converted to rooms to address the needs of the surge). I would then be able to display the current capacity as well as the number of occupied rooms. I would ultimately look at setting some criteria, maybe using text color, to indicate when we are reaching capacity (for example change color to Orange when we are at 80% filled and Red when we reach 100%). In addition, we would need to track limited resources as well, such as Ventilators. I will likely create notes to hold total available ventilators and then reference this to determine remaining ventilators (by summing each patient note where isIntubated == true).

I hope this makes sense. I am not sure if this is the right way to proceed with laying this out or not so any feedback is appreciated.

I am having trouble with getting the numbers to work out. For example, if you look at this latest document I liked in this reply, The Note Available Beds (currently lists 64) but this should be 62 (68 Total Beds - 3 used in SICU - 3 used in MICU). Not sure why this Rule is not working as I have it??

Thanks again, let me know if what I communicated makes sense.

Don

The result of the calculation is correct per the rule you are using in Available Beds:

$Subtitle = $TotalCapacity(/Resources By Location) - $ActiveCensus(/Resources By Location);

because $TotalCapacity in the Resources by Location note is “68” and $ActiveCensus in that note is “4”, thus 68-4=64.

Are you thinking of a different calculation.

In that vein, the $Rule for the Resources by Location note is

$ActiveCensus = sum(children,1)

Which merely counts the children of the agent. (Is that what you want to be doing?). And I see nothing that sets Total Capacity in that agent. What is the rule for Total Capacity? Number of Rooms? Is it a hardcoded setting?

I also noticed that there were some composited notes in the Outline. I suggest running an agent to remove all composites (setting $IsComposite = false); and turn off compositing globally (setting $NeverComposite = true in all notes as well as the default setting for that attribute.

Thanks for this. A few observations, from experience…

Don’t build big maps in the document root—or, as here—maps that will grow big. A few reasons are:

  • As the doc grows the sheer number of things on the map becomes overwhelming. It’s useful to put all the ‘content’ in a separate root-level container to thru-doc stuff like containers of prototypes, templates, action code snippets, etc., and notes related to the ‘how’ of the document.
  • Within the content area, put things of a type together. You’re quite correctly thinking ahead with prototypes. So a good idea might be to have, inside the content branch of the outline, a ‘Locations’ container, to hold locations. Theese containers can have an OnAdd to set the right prototype to aid rapid configuration. Thus the 'Staff' container's OnAdd would be ` Prototype=“Staff”`, etc. But the later shows another easily made sub-par choice.
  • Prototype names. Like as note you’ll wants a folder to hold things of a type, e.g. Staff. so, for prototypes avoid-using a name that might/will be a note or container name. The simplest method is to use a prefix for prototype names. I use ‘p’ (pStaff), some like an asterisk (*Staff). anyway, pick a style you like and use it for all your prototypes. Not only will it avoid name collisions but will make reference to prototypes very clear (especially when using action code). Note that if renaming existing prototypes you will need to review existing rules/edicts/queries/etc that use the old name. The latter task is another good reason to use distinctive prototypes as the later in the process you need to do this the more checking is needed.
  • For (will get) big categories—likely, patients—you may well get to the point where having all notes of a common (proto)type in one container is unwieldy. Watch for using inside() in your code/queries. Likely for the actual work you’ll want to replace inside() with descendedFrom() with an additional & $Prototype==… filter to ignore structural non-content sub-containers, for instance if you split staff into ‘A-M’ and ‘N-Z’ containers.
  • At the early stage, agents and rules are really quick ways to prototype things but be aware that as things grow, now everything needs to be always-on. $AgentPriority can be used to make (some) agents run less frequently. Moving rules to edicts can stop unnecessary over-calculation. Edicts can still be run on demand. Keep rules for where you can’t afford the possibility of data not being correct without (minimal) user effort to update it. The balance here is a very personal thing. I only mention it so if/when agents and rules start to slow down the document, you know there are approaches to deal with that.
    *Dashboard. Think where you want it. If outside the outline branch holding your content/data then you’ll be forced to use agents more that you want. If inside the top level of the content branch you may be able to use table expressions where otherwise you’d use (more) agents.

On the separate issue of table expressions vs. other views, such as Crosstabs. I think the the narrow A vs B context of a Crosstab isn’t the thing here, but Attribute Browser+Column view might. Whether using the latter or Table expression, the way to do this is to calculate these values and store them per-note (where relevant, i.e. not every note) ready for display in TEs or in AB view. Calculate them using action code in a rule (or edict, as explained above).

Thanks again for the help. The most amazing thing I find in this forum is how your insights clear up my understandings and lack of great organization.

To response to a few points, I have been using the current document that I have been sharing as a playground of sorts to try and understand exactly what I need to do. I have realize that I have not abstracted things like I should have in the beginning so I am working to refactor the entire design from the ground up.

Paul - No I did not communicate this very well (And also did not follow good programming practices by naming something that makes no sense). The Agent - Resources by Location (Maybe a better name would be Total Capacity/Use), is collecting all locations (ie MICU, SICU, 4 South, 5 South) so I do not just want to sum the children (this would count the number of locations (or maybe in a hospital framework should call these Wards).

$TotalCapacity in Resources by Location comes from the Total Capacity in each of these locations added together. Again, in my act of building this as I think (Probably not the best idea, but it has allowed me to understand my flaws in thinking and will guide my refactoring) I used $BedCapacityByLocation in the Location Prototype thinking I would need different names for these attributes which in fact I do not. So I should have used a single attribute $TotalBeds or $TotalCapacity. In the Location’s, it would = sum(children,1). Then in the Agent (currently named Resources By Location) it would simply be sum(children, $TotalCapactiy). In the ‘working’ document, I have modified the rule so this now works as I expected.

On a separate note: I have noticed when I make changes in my Rules (for example in the Location Prototype), these did not propagate down to Locations that already contained other notes. Is this something I am doing wrong? Or is there an issue with modifying rules that are containers holding other notes?? To fix this, I removed all of the Patient notes from the MICU and SICU note collections, deleted them and recreated them. When I added the patient notes back the Rules now ran and everything was in sync. I am guessing this is something I am doing wrong in the order I update things, but thought I would ask to see if other people had this problem as well. (This is why in the last version Paul could not see how I arrived at $TotalCapacity - this part of the rule was not there (I think I deleted it in my edits) yet the last calculation remained).

Corrected Document:
COVID-19 Dashboard - Working File.tbx (147.6 KB)

I will respond to Mark below since this is already very long. Thank you for all of the help. I have made far more progress on this over the weekend than I would have ever imagined.

Sincerely Grateful for all the Help!!
Don

Mark,

Wow, there is so much contained in this short reply! Yes, it makes sense and thank you. I can use this as my outline in refactoring this. I really apologize for the messiness of this. When I have used tinderbox for my own personal documents, I have started in the outline and was much more diligent on how I organized things. This being said, I have not used Tinderbox to the level I am using it now with this COVID dashboard. In this light, I need to appreciate all you mentioned with respect to rules, agents and edicts. I completely understand what you are saying and for the most part, I do not need these to run as frequently as I am here with my development of ideas and learning so I appreciate this warning as I move forward on trying to bring this into use (I will likely be using this as a dashboard being sent out 2x pre day so I can always run things as a final before I export, if that makes sense).

I also agree with your thoughts on using Attribute Browser. I think this is where I Am going to find a lot of power for this. I am working on this now so I can further see how to structure things so this becomes useful as a dive into the specifics of patients and locations.

Thanks again for all of the help and pointing me in the right direction for exploration!

Appreciate everything.

Don

1 Like

No, please don’t feel a need to apologise. The real world is messy. Luckily we have a tool to work through that.

Paging @JFallows who’s ideas worked so hard to convince all of value of such a feature.

The root issue is probably breaking an inheritance chain. If a prototype has a $Rule, and then we edit the $Rule in one or more of the notes that use that prototype, the local edits take precedence over the inherited $Rule. It’s a common mistake and easy to fall into – @mwra and I were exchanging thoughts about that the other day, as a matter of fact.

In the case where inheritance of $Rule or $KeyAttributes or other inherited value of an attribute gets broken, the QuickStamp is my favorite (quick) method to fix the error. Here’s how:

2 Likes

A general comment about this sort of project. Usually, the advice is to let structure of a document emerge as you develop the notes, etc. However, emergent structure is not always the best approach to developing something that will be used for tracking and reporting. @DMV you’ve been sketching your ideas with Tinderbox and iterating toward a solution. When I get to that stage, I set aside Tinderbox for a while, and with pen and paper (metaphorically or actually) I sketch out a more formal visual spec for the document I want. Then I go back fresh to Tinderbox and build based on the sketch.

A problem with “emergent structure” is what I see you’ve encountered. You change the idea for what prototypes or containers you want, and spend time fiddling with prototype edits, or various agents, etc., and then sometimes end in a debugging muddle. To me that’s a clue to step back, make some sketches and specs, and then start fresh.

2 Likes