blue-button / bluebutton.js Goto Github PK
View Code? Open in Web Editor NEWThe Blue Button JavaScript Library
Home Page: blue-button.github.io/bluebutton.js
License: Other
The Blue Button JavaScript Library
Home Page: blue-button.github.io/bluebutton.js
License: Other
In C-CDA any code can have multiple translations.
May we please have some?
Expose NPI number if available
In addition to the core groups we have so far, it would be very useful to have access to metadata associated with the provided document.
This might include:
A relatively important one to get in there, even if it's just the language code (eg "EN") that comes through.
EMERGE has released a set of C-CDAs:
http://cl.ly/1N0T1s301l1m
BB.js is having some trouble with these. For example
code: "ASSERTION", code_system: "2.16.840.1.113883.5.4"
...
When you see XML like:
<doseQuantity value="1"/>
It's effectively shorthand for
<doseQuantity value="1" unit="1"/>
The important thing is that a doseQuantity has a unit (not always implied). So the above may mean "1 pill," or "one inhalation" or whatever is appropriate. But you may also sometimes see:
<doseQuantity value="100" unit="mg"/>
So it's important to capture this fact in the JSON rendering (again, for consistent queryability) rather than just rendering it as the string "1" or "100".
Each problem has an observation whose value defines the actual problem. E.g.
<code code="409586006" codeSystem="2.16.840.1.113883.6.96" displayName="Complaint"/>
<value xsi:type="CD" code="233604007" codeSystem="2.16.840.1.113883.6.96" displayName="Pneumonia"/>
Right now bb.js
is extracting
"name": "Complaint",
"status": "Active",
"age": 57,
"code": "409586006",
"code_system": "2.16.840.1.113883.6.96"
... but this should be "name: pneumonia, code: 233604007..."
I'm curious, why return null fields instead of empty fields? Is there a specific reason?
Otherwise it seems like it'd be good to stick with most Web APIs' convention of returning empty as opposed to null fields. Generally this convention pertains mostly to text fields, which is why it seems all the more pertinent here — all we're dealing with are text fields.
FWIW it's not the end of the world if bb.js is sticking to its story of null rather than empty because at least there's still only one way to have an empty string: null (as opposed to null and ""). Again, just curious.
Coming from a Django-heavy background. Naturally.
Translations are translations of codes, so they should be attached to codes. The following free-floating translation attached to your encounter example doesn't make sense to me:
{
"date": "2000-05-07T05:00:00.000Z",
"name": "Office consultation - 15 minutes",
"code": "99241",
"code_system": "2.16.840.1.113883.6.12",
"code_system_name": "CPT",
"code_system_version": "4",
"finding": {
"name": "Bronchitis",
"code": "32398004",
"code_system": "2.16.840.1.113883.6.96"
},
"translation": {
"name": "Ambulatory",
"code": "AMB",
"code_system": "2.16.840.1.113883.5.4",
"code_system_name": "HL7 ActEncounterCode"
},
...
This should probably read:
{
"date": "2000-05-07T05:00:00.000Z",
"encounter_type": {
"name": "Office consultation - 15 minutes",
"code": "99241",
"code_system": "2.16.840.1.113883.6.12",
"code_system_name": "CPT",
"code_system_version": "4",
"translations": [{
"name": "Ambulatory",
"code": "AMB",
"code_system": "2.16.840.1.113883.5.4",
"code_system_name": "HL7 ActEncounterCode"
}],
Also note that translations are multiple cardinality.
E.g.,
<effectiveTime>
<low value="195001"/>
</effectiveTime>
will return a nice date in bb.js. But
<effectiveTime>
<low value="1950"/>
</effectiveTime>
will not. It will return null for the date.
Feel free to close if this is expected functionality.
Hi Tom,
I was looking at:
http://bluebutton.blacktm.com/json
Do you think you could put a small icon/note next to each section saying if it is being parsed or using temporarily hard-coded stuff?
Best,
Ryan
Use <script id="data" type="application/xml">...</script>
for the HTML build, instead of a hidden textarea
(much less hacky). Test build across all platforms.
Just noticed in labs that values are converted from strings with parseInt
but that turns "13.2" into 13.
Should use parseFloat
instead.
Some problems store their code/displayName in a translation tag instead of in the actual value tag. Perhaps we should check for this.
I'm working with the demo of the parser at http://blue-button.github.io/blue-button-for-developers/docs/js/demo.html#document-section
I'm trying to do a little eyeball QA on the before and after and running into some challenges.
The CCDA XML lists a weight measurement of 195 lbs on 3/30/12 and 162 lbs on 1/24/13.
The JSON lists a vital of 195 lbs on 10/25/11, 4/30/12, 2/24/13. It lists vitals for 162 lbs also on 10/25/11, 4/30/12, 2/24/13.
This is an open question of how we test BlueButton.js (or really any dev tool) with sample patient data given that no reference implementation of the CCDA exists, and samples contributed by vendors are often low quality or incomplete.
Since many vendors/providers will be implementing the CCDA standard to comply with Meaningful Use Stage 2, ONC has created the SITE group to help actually implement these standards (it's not easy folks). Their EMERGE project will serve to be an authoritative source of high-quality sample CCDAs. @nayanjain and I are working closely with them to get this sample data in the hands of developers. (For the time being, they have the tool behind a login – I'll try to get some demo accounts.)
I think we should leverage the work being done by SITE and use sample data from their EMERGE project, the same resource EMR vendors, the VA, and others (?) will be using to implement their CCDAs. The benefit of this approach is that if/when we find difficulties using/parsing the CCDA, feedback can be sent back to SITE, and ultimately back to the standards committee if need be.
Thoughts?
Other resources:
HL7 implementation guide
@jmandel's sample_ccdas
What is the grouping of the labs output?
The only sample file I have that seems to parse correctly groups three results under a PLT object, but one of those objects is PLT as well. Is it supposed to be a panel?
Should this panel have a date associated with it? Is there a reference to when the lab/panel/whatever was ordered?
BB.js currently supports all browsers with DOMParser (non-IE and IE9+). Should we attempt to add support for IE8 and below? This would require using ActiveX or some other hackety hack.
When performing rake build
, the build script throws an error: Unable to access jarfile vendor/compiler-r2388.jar
I think this is a regression... but C-CDA uses multiple cardinality for given name, and for street address lines.
The effectiveTime
of a medication is used for two distinct purposes (switched on the @xsitype
attribute):
If you see an xsitype of PIVL
or EIVL
, this indicates the effectiveTime actually represents a dose period (not a "patient is taking the medication" date range).
Here's how the logic works:
https://github.com/chb/ccdaReceiver/blob/nodejs/lib/ccda/ccd.js#L320
Ever considered release notes for bb.js?
I just pulled latest master in a while and am having to smoke test bb.js to try and figure out what breaking changes I may need to account for.
For example, labs no longer include code_system
and code_system_name
(introduced in 0233333). This isn't breaking anything for us but I could see it breaking frontends where systems rely on data once bb.js starts passing it through, and potentially backends that don't code around attributes not always existing/being made available.
now, you have to test against a bunch of different fields, even if they're all null. Should be able to simply test against demographics.guardian.
<id root="2.16.840.1.113883.4.6"/>
Does not work in IE. Investigating XML parsing behavior cross-broswer (IE 6-9 does not have window.DOMParser
and must use ActiveXObject
).
Update 1:
Now works in IE10 using the native window.DOMParser
. Still busted using IE 6-9's ActiveXObject
.
(Apparently parentElement
is a non-standard property but still returns undefined
in IE, adding to hours of deep bug hunting fun. FML. Changed to parentNode
.)
Update 2:
Looks like it should work in all browsers using window.DOMParser
, this includes IE 9+. Now working on IE 6-8 using ActiveXObject
.
Josh:
Original implementation included completely separate pathways for parsing different document types (CCDA, C32). The new implementation should diverge at the point of parsing and data extraction, then join before constructing the final data object. This will reduce redundancy and make it generally easier to test and maintain.
Probably already on your TODO list, but right now allergy dates are being initialized to null and never set.
Right now dates are sometimes points, sometimes ranges, and sometimes a combination. When a range is represented, different words are used in different places for the boundaries.
It's reasonable to use a date range for some resources (meds, problems, encounters), and a single point for others (lab result, vital sign). But I'd use different property names in these to cases, or else just always use a JS object (rather than object in some cases and Date/string in others).
"effective_time": {
"low": "2011-04-01T06:00:00.000Z",
"high": "2012-04-01T06:00:00.000Z"
},
"date": {
"value": null,
"low": null,
"high": null
},
"observation_date": {
"low": null
},
"date": "2000-05-07T05:00:00.000Z",
"date": {
"from": "1998-03-31T06:00:00.000Z",
"to": "2011-02-03T06:00:00.000Z"
},
(At least for inpatient encounters, a start and end date are essential.)
For example in Labs, rather than repeating:
var name = el.attr('displayName'),
code = el.attr('code'),
code_system = el.attr('codeSystem'),
code_system_name = el.attr('codeSystemName');
You should parse the code in a consistent way (including translations if present), and abstract out that logic. Then you can given the code a property name to attach it to the lab
(For example in SMART we use semantic labels like "labName", so we'd have an individual result and say result.labName.code
, or result.labName.label
).
When representing a code, it may be fine to include the displayName
as extra (helpful) info in the JSON payload. But in cases where you're trying to avoid using a code altogether, it's not a safe approach to simply use the displayName
value from the underlying document.
Two reasons:
displayName
is optional (and may sometimes be missing)displayName
you want for a given code, so documents may have different names for the same code -- and app developers won't know what to expect.Simplest example: you're extracting a text description for race to make JSON snippets like:
"race": "White",
Great! But don't just copy patient.tag("raceCode").attr("displayName")
into this field. Rather, use patient.tag("raceCode").attr("code")
, and map it explicitly to a display name that you want to associate with "White." This way apps that do clinical decision support based on race won't fail to match terms because of differences in spelling, diction, language, or even capitalization...
I think this is just a typo that's happened to work out in your particular environment, but lines 488-490 prepare an incoming 'source' blob, but then parse the contents of the 'xml' variable.
source = source.replace(/^\s+|\s+$/g, "");
if(source.substr(0, 5) == "<?xml") {
xmlDOM = Core.parseXML(xml);
should probably become:
source = source.replace(/^\s+|\s+$/g, "");
if(source.substr(0, 5) == "<?xml") {
xmlDOM = Core.parseXML(source);
I added bluebutton to my package.json like this:
"bluebutton": "git://github.com/blue-button/bluebutton.js.git"
Just npm installed and tried to require("bluebutton") and I get this:
> bb = require("bluebutton");
TypeError: Arguments to path.resolve must be strings
at Object.exports.resolve (path.js:313:15)
at tryPackage (module.js:127:23)
at Function.Module._findPath (module.js:190:18)
at Function.Module._resolveFilename (module.js:336:25)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at repl:1:6
at REPLServer.self.eval (repl.js:110:21)
at repl.js:249:20
Requiring the full path works fine:
> bb = require("./node_modules/bluebutton/build/bluebutton.js");
[Function]
Is this a known issue? I'm I doing something stupid? Any ideas?
Upgraded my npm {1.2.18 -> 1.2.32} and node {v0.10.5 -> 0.10.12} and had the same error.
For example with vitals, you could find entries in one of two places:
el = xmlDOM.template('2.16.840.1.113883.10.20.22.2.4.1');
entries = el.elsByTag('entry');
if (!entries.length) {
el = xmlDOM.template('2.16.840.1.113883.10.20.22.2.4');
entries = el.elsByTag('entry');
}
The former is preferred, but I've seen the latter in production systems.
There's a little inconsistency in this right now.
For example, bb.demographics()[0].phone.home
returns a list, even if there's only one number listed. On the other hand, bb.demographics()[0].guardian.phone.home
returns a string.
I prefer the former, just because it's easy to know that you'll always have to iterate through a list, rather than having to check to see whether it's a list or a string.
Anytime a date appears, and it's not via the .json() method, we should try to parse the date into a proper JS Date object.
Then things like sorting, formatting for display, etc. become much easier.
I'm running the same data using bb.js vs. the demo site and getting inconsistent results between the two. What's stranger is that it's only happening with certain CCDA files.
var xml = fs.readFileSync(xmlfilepath, 'utf8', function(err, data) {
if (err) {
console.log(err);
}
});
var bb = BlueButton(xml);
console.log(bb.demographics().json());
EXAMPLE 1: When I run this code against one of the files from the Direct Transport Sandbox — CCDA_CCD_b1_AllPerfsAddAPtoP3.xml — I get no data back (again this is just bb.demographics().json()):
Error: date is not a string
{
"name": {
"prefix": null,
"given": [],
"family": null
},
"dob": null,
"gender": null,
"marital_status": null,
"address": {
"street": [],
"city": null,
"state": null,
"zip": null,
"country": null
},
...
Whereas the demo site shows the proper demographics data from the XML:
EXAMPLE 2: When I run bb.js against a copy of the "Blue Button Reference CCDA" XML from the demo site I get a nice response (again, this is bb.demographics().json():
Error: date is not a string
{
"name": {
"prefix": null,
"given": [
"Adam"
],
"family": "Everyman"
},
"dob": "1962-10-22T00:00:00.000Z",
"gender": "Male",
"marital_status": "Never Married",
"address": {
"street": [
"17 Daws Rd.",
"Apt 27"
],
"city": "Blue Bell",
"state": "MA",
"zip": "02368",
...
And of course the Reference CCDA works just fine at the demo site.
NB: I'm running bb.js via Node.js, not in a browser. I can't think of any reasons that would be the culprit but please point it out if you think it is. Another possible local culprit could be using fs.readFileSync, not sure if there's a better way to be reading in this XML...
(SNOMED, LOINC, RxNorm, etc).
Example: http://phinvads.cdc.gov/vads/ViewCodeSystemConcept.action?oid=2.16.840.1.113883.6.238&code=2113-9
Add separate mapping table from canonical name --> OID + URL + potentially other useful info
Because according to C-CDA spec, this code is fixed as:
2.16.840.1.113883.5.4
(ActCode) = ASSERTION
(
The example file you're using appears to have a mistake where the code
is:
<code code="416098002" displayName="drug allergy" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT"/>
)
In the example C-CDA at: http://bluebutton.blacktm.com/json
It looks like the code for PLT (platelets, a component of a complete blood count) is being pulled up in the header for the whole lab panel (which should be binding to the "CBC WO DIFFERENTIAL" code)
[
{
"name": "PLT", // <------- this should be "CBC WO DIFFERENTIAL"
"code": "26515-7", <------ this should be "43789009"
"code_system": "2.16.840.1.113883.6.1", <------- this should be "2.16.840.1.113883.6.96"
"code_system_name": "LOINC",
"results": [
...
"date": "2000-04-23T07:00:00.000Z",
"name": "PLT",
"value": "123",
"unit": "10+3/ul",
"code": "26515-7",
(just putting this here for documentation purposes)
demographics() should return a bare object, rather than a list of objects.
Even if the record targets more than one person, we should just not support that for now. It would be too confusing for folks to know what to do with two sets of demographics, and I'd think the use cases for multi-person records are relatively few.
Per #60
It seems like jsdom will freak out if you're using CRLF line endings and putting new lines between your attributes. I'm not sure if it's possible for us to convert all line endings to LF before parsing a doc but we should look into it. Note that this only affects the node.js parser.
I'm new to node.js. Is this the proper way to load the library?
> require('./bluebutton.js');
ReferenceError: window is not defined
at Object.<anonymous> (/Users/neil/Desktop/bluebutton/bluebutton.js:2235:1)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at repl:1:1
at REPLServer.self.eval (repl.js:110:21)
at repl.js:249:20
(Copying from https://groups.google.com/forum/#!topic/bluebuttondev/zGjyb4MF_1E)
Some files we're parsing are falling down; they return null for all values. When eyeballing the files they look to be properly-formatted; they're definitely CDA files. So I'm assuming there's some nuance here I'm unaware of.
One hypothesis based on a cursory analysis: maybe some templateIds are supported vs. others are not? E.g., does it sound right that bb.js would return null for all values if we're parsing Continuity of Care documents, even though the document itself is properly CDA-formatted? (I'm still a bit hazy as to what bb.js expects in terms of a file it accepts for parsing. Is it any CCDA file?[1])
For example, I just added
<templateId root="2.16.840.1.113883.10.20.22.1.1"/>
[2]
after the opening
<typeId ...>
line in a CDA file that was returning null for everything via bluebutton.js and now all of a sudden bb.demographics() returns the actual demographics data from the file (i.e., non-null values).
Anyone got some wisdom here?
Any insight best practices for debugging issues like this?
[1] I know bb.js is also still under heavy development and AFAICT is still looking to support a wider array of files, etc. If there's a preferred channel for giving more secure feedback to widen that array please let me know.
[2] For posterity I got that templateId from https://github.com/blue-button/bluebutton.js/blob/master/lib/ccda/demographics.js#L26.
Immunizations should be classified as given vs. not, based on the @negationInd
attribute. When not give, a patient refusal reason should also be included.
For example the following is silly:
"device": {
"name": "General Acute Care Hospital",
"code": "GACH",
"code_system": "2.16.840.1.113883.5.111"
}
The hospital isn't listed as a device; it's listed as Service Delivery Location (templateId = 2.16.840.1.113883.10.20.22.4.32
). You'll want to identify devices by [@templateId = '2.16.840.1.113883.10.20.22.4.37']/../playingDevice/code...
(This appears to stem from the use of getElementsByTag
at https://github.com/blue-button/bluebutton.js/blob/master/src/core.js#L45, which recurses and finds nested elements, not just direct-children -- which can make the convenience wrappers fail in surprising ways when it doesn't find what it expects at the top of the hierarchy.)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.